Si ‘Test’ est une classe ordinaire, y a-t-il une différence entre:
Test* test = new Test;
et
Test* test = new Test();
Allons de l’avant, car certaines différences peuvent affecter le comportement de votre code. Une grande partie de ce qui suit provient des commentaires faits dans un article “Old New Thing” .
Parfois, la mémoire renvoyée par le nouvel opérateur sera initialisée, et parfois elle ne le sera pas selon que le type que vous modifiez est un POD (old old data) , ou une classe contenant des membres POD et utilisant un constructeur par défaut généré par le compilateur.
Assumer:
struct A { int m; }; // POD struct B { ~B(); int m; }; // non-POD, comstackr generated default ctor struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m
Dans un compilateur C ++ 98, les éléments suivants doivent se produire:
new A
– valeur indéterminée new A()
– initialiser à zéro
new B
– construction par défaut (B :: m est non initialisé)
new B()
– construction par défaut (B :: m est non initialisé)
new C
– construction par défaut (C :: m est initialisé à zéro)
new C()
– construction par défaut (C :: m est initialisé à zéro) Dans un compilateur conforme C ++ 03, les choses devraient fonctionner comme ceci:
new A
– valeur indéterminée new A()
– initialise la valeur A, qui est une initialisation nulle car c’est un POD.
new B
– initialise par défaut (laisse B :: m non initialisé)
new B()
– initialise la valeur B qui initialise à zéro tous les champs puisque son moteur par défaut est généré par le compilateur et non par l’utilisateur.
new C
– initialise par défaut C, qui appelle le ctor par défaut.
new C()
– valeur initialise C, qui appelle le ctor par défaut. Donc, dans toutes les versions de C ++, il y a une différence entre les new A
et les new A()
car A est un POD.
Et il y a une différence de comportement entre C ++ 98 et C ++ 03 pour le cas new B()
.
C’est l’un des coins poussiéreux de C ++ qui peut vous rendre fou. Lorsque vous construisez un object, parfois vous voulez / avez besoin des parens, parfois vous ne pouvez absolument pas les avoir, et parfois cela n’a pas d’importance.
new Thing();
est explicite que vous voulez un constructeur appelé alors que new Thing;
est supposé impliquer que cela ne vous dérange pas si le constructeur n’est pas appelé.
S’il est utilisé sur une structure / classe avec un constructeur défini par l’utilisateur, il n’y a pas de différence. Si appelé sur une structure / classe sortingviale (par exemple struct Thing { int i; };
), alors new Thing;
est comme malloc(sizeof(Thing));
alors que new Thing();
est comme calloc(sizeof(Thing));
– le zéro est initialisé.
Le piège se situe entre:
struct Thingy { ~Thingy(); // No-longer a sortingvial class virtual WaxOn(); int i; };
Le comportement de la new Thingy;
vs new Thingy();
dans ce cas changé entre C ++ 98 et C ++ 2003. Voir l’explication de Michael Burr sur comment et pourquoi.
Non, ils sont pareils Mais il y a une différence entre:
Test t; // create a Test called t
et
Test t(); // declare a function called t which returns a Test
Ceci est dû à la règle de base C ++ (et C): Si quelque chose peut éventuellement être une déclaration, alors c’est une déclaration.
Edit: Concernant les problèmes d’initialisation concernant les données POD et non POD, alors que je suis d’accord avec tout ce qui a été dit, je voudrais juste souligner que ces questions ne s’appliquent que si la chose nouvellement créée ou construite n’a pas de constructeur défini par l’utilisateur. S’il existe un tel constructeur, il sera utilisé. Pour 99,99% des classes judicieusement conçues, il y aura un tel constructeur, et les problèmes pourront être ignorés.
En général, nous avons l’initialisation par défaut dans le premier cas et l’initialisation de la valeur dans le second cas.
Par exemple: en cas avec int (type POD):
int* test = new int
– nous pouvons avoir n’importe quelle initialisation et valeur de * test.
int* test = new int()
– * test aura une valeur de 0.
comportement suivant dépend de votre type Test. Nous avons des cas différents: Test avec constructeur par défaut, Test avec constructeur par défaut, Test avec membre POD, membre non POD …
En supposant que Test est une classe avec un constructeur défini, il n’y a pas de différence. Cette dernière forme rend un peu plus clair que le constructeur de Test est en cours d’exécution, mais c’est à peu près tout.