C++ 对象创建和构造函数

Posted

技术标签:

【中文标题】C++ 对象创建和构造函数【英文标题】:C++ object creation and constructor 【发布时间】:2012-02-05 07:52:12 【问题描述】:

我现在正在学习ctors,有几个问题。在这些行:

Foo obj(args);

Foo obj2;
obj2 = Foo(args);

Foo obj3 = Foo(args);

第一部分:只有一个名为 (Foo) 和 obj 的构造函数被初始化。因此,创建了 1 个对象。

第二部分:创建临时对象obj2,为其调用默认ctor。下一行我们创建Foo 的另一个副本并将其副本传递给operator=()。那正确吗?所以,3 个本地临时对象,2 个构造函数调用。

第三部分:创建1个对象Foo并将其副本传递给operator=()。因此,有 2 个临时对象和 1 个 ctor 调用。

我理解对了吗?如果是真的,编译器(例如最后一个 gcc)会在常见情况下优化这些吗?

【问题讨论】:

operator=() 通常通过引用接收它的参数,所以在调用它时没有副本。 obj3 实际上是使用复制构造函数而不是赋值运算符创建的。 【参考方案1】:

我先评论第三个:

Foo obj3=Foo(args);

它不使用称为复制分配的operator=。相反,它调用复制构造函数(理论上)。这里没有任务。所以理论上,有两个对象创建,一个是临时的,另一个是obj3。编译器可能会优化代码,完全省略临时对象的创建。

现在,第二个:

Foo obj2;         //one object creation
obj = Foo(args);  //a temporary object creation on the RHS

这里第一行创建一个对象,调用默认构造函数。然后它调用operator= 传递由表达式Foo(args) 创建的临时对象。所以有两个对象,只有operator= 采用const 引用的参数(这是它应该做的)。

关于第一个,你是对的。

【讨论】:

好的,谢谢。但无论如何,在第一种情况下,只创建了 1 个 Foo 类型的对象,在第三种情况下:2 个对象? 不,根据规范,第 1 部分和第 3 部分是指定同一事物的两种方式。实现上没有区别。 @MrLister:不。13 之间存在细微差别。只需编写一个测试代码,并制作复制构造函数private。第一个会编译,第三个不会! 噢。我敢肯定,当我学习 C++ 时,我就被教过这个。但你是对的,它不会编译。而且我找不到将它作为同义词的引用。所以,谢谢和抱歉。我会要回我的钱。【参考方案2】:

    是的,Foo obj(args) 创建一个 Foo 对象并调用一次 ctor。

    obj2 不被视为临时对象。但就像 1 Foo obj2 创建一个对象并调用 Foo ctor。假设你的意思是obj2 = Foo(args) 用于下一行,这一行会创建一个临时 Foo 对象,然后调用obj2.operator=()。因此,对于第二个示例,只有一个临时对象,一个非临时对象,Foo ctor 被调用两次(一次用于非临时对象,一次用于临时对象)并且 operator=() 被调用一次。

    不,此行不调用operator=()。当您使用= 语法初始化obj3 时,几乎就像您使用了括号一样:Foo obj3(Foo(args)); 所以这一行创建了一个临时对象,然后调用 Foo 复制 ctor 使用该临时对象初始化 obj3。

【讨论】:

【参考方案3】:

您的术语有点混乱。

对象objobj2obj3 不称为“临时对象”。只有在分配给 obj 之前在第 3 行中创建的实例是临时对象。

此外,您不会创建“Foo 的副本”,而是创建“Foo 的实例”或“Foo 类型的对象”。

【讨论】:

以上是关于C++ 对象创建和构造函数的主要内容,如果未能解决你的问题,请参考以下文章

C++的六个函数

C++创建派生类对象时,调用构造函数顺序

C++中,建立子类对象的时候,会调用基类的构造函数,

c++ 在创建时将构造函数参数从父对象传递给子对象

在c++中创建了类,但在创建新对象时,编译显示:不存在默认构造函数

C++对象模型