verschillende manieren om een ​​object in C++

Stel je voor deze klasse:

class Entity {
public:
    int x, y;
    Entity() : x(0), y(0) { }
    Entity(int x, int y) : x(x), y(y) { }
}

en hier zijn meerdere manieren om de klas te initialiseren met wat ik denk dat ik weet:

Entity ent1;                //Uses the default constructor, so x=0 and y=0
Entity ent2();              //Uses the default constructor, so x=0 and y=0 (Not sure)
Entity ent3(1, 2);          //Made constructor, so x=1 and y=2
Entity ent4 = Entity();     //Default constructor, so x=0 and y=0
Entity ent5 = Entity(2, 3); //Made constructor, so x=2 and y=3

Ik weet dat het mogelijk is om een ​​object op het heapgeheugen te maken, maar dat is niet wat ik op zoek ben op dit moment.

Mijn vraag is, wat is het verschil tussen deze manieren om een ​​object initialiseren?

Ik weet niet zeker welke ik moet gebruiken wanneer.


Antwoord 1, Autoriteit 100%

Entity ent1;

De bovenstaande verklaring gebruikt standaardconstructeur van de klasse Entity.


Entity ent2();

De bovenstaande verklaring wordt door de compiler behandeld als een functie-prototype als dat mogelijk is. Het staat bekend als een geval van meest vexing parse (MVP) en het bestaan ​​ervan leidde tot het uiterlijk van misleidende “slimme domme regel”: “Gebruik nooit haakjes”.


In de verklaring zoals deze wordt een door de gebruiker gedefinieerde constructeur ingeroepen voor ent3:

Entity ent3(1, 2);

Een ander geval waarin MVP kan toeslaan is zoiets als dit:

Entity ent3_1(int(a), int(b));  // It's not what it looks like.

ent3_1hierboven is geen variabele. De instructie declareert een functie met twee int-parameters. int(a)is hetzelfde als int aen is een erfenis van C-taal en declaratiesyntaxis daar.


Entity ent4 = Entity();

ent4is een juisteversie van ent2case tot C++11. Standaardconstructor wordt aangeroepen als onderdeel van waarde-initialisatie. Zijn vorm maakt het mogelijk om een ambiguïteitsoplossingsprincipe te vermijden dat ent2en ent3_1onjuist maakt. Gelijkteken hier is geen toewijzing, want hier zal geen operator=aanroep plaatsvinden. Het maakt deel uit van de declaratiesyntaxis die bedoeld is om de initialisatie-expressie te markeren.


Entity ent5 = Entity(2, 3);

ent5is een versie van ent3 case. Door de gebruiker gedefinieerde constructor aangeroepen als onderdeel van waarde-initialisatie.


Uw vraag is getagd als C++11 en C++11 staat uniforme initialisatiesyntaxis toe:

Entity ent12{};     // This is a legal alternative of ent2 case
Entity ent13{1, 2}; // A call to constructor or member initialization
Entity ent13{ int(a), int(b) }; // Not a function anymore
Entity ent14 = {};              // Not an assignment
Entity ent15 = Entity{2, 3};    // Not an assignment either!

Houd er rekening mee dat uniforme initialisatiesyntaxis een voorbehoud heeft. bijv. deze regel

std::vector<int> v(10); 

declareert een vector van 10 elementen. Maar deze

std::vector<int> v{10};

declareert een vector die is geïnitialiseerd met een enkel element van het type int met waarde 10. Dit gebeurt omdat std::vectoreen constructor heeft met de volgende handtekening gedefinieerd:

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

In het geval dat u geen van beide () kunt gebruiken zonder MVP of {} te activeren zonder een ongewenste constructor aan te roepen, maakt de syntaxis van de waarde-initialisatietoewijzing het mogelijk om het probleem op te lossen.

Addendum: Moet CppCon 2018: Nicolai Josuttis “The Nightmare of Initialization in C++”

Other episodes