C ++构造函数语法

时间:2009-02-25 17:45:42

标签: c++ constructor

简单问题:以下陈述是否相同?或者是第二个在幕后做更隐含的事情(如果是,那又怎样?)

myClass x(3);
myClass x = myClass(3);

谢谢!

4 个答案:

答案 0 :(得分:25)

它们并不完全相同。第一种称为“直接初始化”,而第二种称为“复制初始化”。

现在,标准制定了两条规则。第一种是直接初始化和复制初始化,其中初始化器是初始化对象的类型。第二个规则是在其他情况下进行复制初始化。

因此,从这个角度来看,两者都被称为一个 - 第一个 - 规则。如果您具有相同类型的复制初始化,则允许编译器删除副本,因此它可以构造您直接创建到初始化对象中的临时文件。因此,您可以使用生成的相同代码完成最终结果。但是复制构造函数,即使复制被省略(优化出来),仍然必须可用。即如果你有一个私有拷贝构造函数,如果它出现的代码无法访问它,那么该代码是无效的。

第二种称为复制初始化,因为如果初始化程序的类型是不同的类型,则在尝试将右侧隐式转换为左侧时会创建一个临时对象:

myclass c = 3;

当存在一个带有int的构造函数时,编译器会创建一个myclass类型的临时对象。然后用它临时初始化对象。同样在这种情况下,可以直接在初始化对象中创建临时创建。您可以通过在类的构造函数/析构函数中打印消息并使用GCC选项-fno-elide-constructors来执行这些步骤。它不会试图删除副本。

另外,上面的代码与赋值运算符无关。在这两种情况下,会发生什么是初始化。

答案 1 :(得分:8)

如果编译器未实现复制省略,则第二个可能会或可能不会要求额外的myclass对象构造。但是,大多数构造函数都默认启用了复制省略,即使没有任何优化开关也是如此。

注意初始化,而构造永远不会调用赋值运算符。

始终,请记住:

  

赋值:已存在的对象获取新值

     

初始化:新对象在其诞生时获取值。

答案 2 :(得分:5)

在第二个中,首先创建一个临时对象,然后使用myClass的复制构造函数将其复制到对象x中。因此两者都不一样。

答案 3 :(得分:4)

我写下以下内容尝试并说明了解发生了什么:

#include <iostream>

using namespace std;

class myClass
{
public:
    myClass(int x)
    {
        this -> x = x;
        cout << "int constructor called with value x = " << x << endl;
    }

    myClass(const myClass& mc)
    {
        cout << "copy constructor called with value = " << mc.x << endl;
        x = mc.x;
    }

    myClass & operator = (const myClass & that)
    {
        cout << "assignment called" << endl;
        if(this != &that)
        {
            x = that.x;
        }
        return *this;
    }

private:
    int x;
};

int main()
{
    myClass x(3);
    myClass y = myClass(3);
}

当我编译并运行此代码时,我得到以下输出:

$ ./a.out
int constructor called with value x = 3
int constructor called with value x = 3

这将似乎表示在main函数中进行的两次调用之间没有区别,但这是错误的。正如litb指出的那样,复制构造函数必须才能使此代码正常工作,即使在这种情况下它被忽略了。为了证明这一点,只需将上面代码中的复制构造函数移动到类定义的私有部分即可。您应该看到以下错误:

$ g++ myClass.cpp 
myClass.cpp: In function ‘int main()’:
myClass.cpp:27: error: ‘myClass::myClass(const myClass&)’ is private
myClass.cpp:37: error: within this context

另请注意,赋值运算符从不调用。