【问题标题】:C++ Object Instantiation vs AssignmentC++ 对象实例化与赋值
【发布时间】:2012-08-04 22:11:18
【问题描述】:

这有什么区别:

TestClass t;

还有这个:

TestClass t = TestClass();

我预计第二个可能会调用构造函数两次,然后是 operator=,但实际上它只调用了一次构造函数,就像第一个一样。

【问题讨论】:

    标签: c++ constructor default-constructor copy-assignment


    【解决方案1】:
    TestClass t;
    

    调用默认构造函数。

    TestClass t = TestClass();
    

    是一个复制初始化。它将调用TestClass() 的默认构造函数,然后调用复制构造函数(理论上,复制受制于复制省略)。 这里没有分配任务

    还有直接初始化的概念:

    TestClass t(TestClass());
    

    如果要使用赋值运算符:

    TestClass t;
    TestClass s;
    t = s;
    

    【讨论】:

    • 我想知道,第二个是否也可以在 C++11 中调用移动构造函数?
    • 对复制构造函数的调用可能会被优化掉(通常是这样)。
    • @Mahesh 复制会被省略。
    • @Mahesh - 这只是 RVO 的实际应用
    • 啊,复制省略和将初始化误认为赋值是让我绊倒的原因。匿名 TestClass() 是一个右值。因为它没有名称并且无论如何都注定要销毁,所以编译器只是跳过副本并直接使用它。我期望的行为可以来自TestClass t; t = TestClass();,它确实做了两个构造和一个赋值。
    【解决方案2】:

    第一种情况非常简单——使用默认构造函数构造一个实例。

    第二个类是构造一个匿名对象,然后调用复制构造函数。注意这里=不是赋值,它类似于(但不是identical)写法:

    TestClass t(TestClass());
    

    我们可以通过使其不可用来验证这需要复制构造函数可用,例如:

    #include <iostream>
    
    struct TestClass {
      TestClass() { std::cout << "Ctor" << std::endl; }
      TestClass(const TestClass&)  = delete;
    };
    
    int main() {
      TestClass t = TestClass();
    }
    

    由于删除了复制构造函数而无法编译。 (在 C++03 中,您可以改用 private:)。

    实际上最有可能发生的事情是您的编译器正在执行Return value optimisation,因此允许它完全省略对复制构造函数的调用提供一个合适的存在并且可以访问。 p>

    【讨论】:

    【解决方案3】:

    在第一个中,您隐式调用了默认构造函数。在第二个中,您明确地调用它。

    【讨论】:

    • TestClass t(0)TestClass t = TestClass(0) 有什么不同吗?
    • 嗯,没有什么不同。但由编译器决定。它要么像第一个声明那样做,要么创建一个临时对象,稍后将其复制到“t”。如果这样做(通过创建临时对象),则将在删除创建的临时对象后调用类析构函数。但是通过一种或另一种方式,您会得到相同的结果。
    【解决方案4】:

    后者可以调用复制构造函数,因此需要一个是公共的。

    编辑:我确实从您使用的类型名称中得出了太大的结论。上面的句子仅适用于类类型(即不是 POD)。对于 POD 类型,前者不初始化变量,而后者使用所谓的“默认”值对其进行初始化。

    【讨论】:

      猜你喜欢
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      相关资源
      最近更新 更多