2016-09-27 104 views
1

在这个程序中,我完全理解为什么主函数的第一部分失败并需要注释 - 在我在TestingClass中实现值ctor后没有隐式的默认ctor。完全合乎逻辑。但是,我发现第二部分(test2对象的创建)成功,至少在gcc 4.8.4中,我有点惊讶。没有默认构造函数的初始化时的赋值

#include <iostream> 
using namespace std; 

class TestingClass 
{ 
    public: 
    TestingClass(int inVal) 
    { 
     val = inVal; 
    } 

    int val; 
}; 

TestingClass testingCreator() 
{ 
    return TestingClass(100); 
} 

int main() 
{ 
    /* 
    TestingClass test1; 
    test1 = testingCreator(); 
    cout << "Test1: " << test1.val << endl; 
    */ 

    TestingClass test2 = testingCreator(); 
    cout << "Test2: " << test2.val << endl; 
} 

关于它的思考,这也是情理之中,因为对象,TEST2,以后再也没有被修建/初始化存在,但大多数人在这种思维方式初始化为只是做了声明和赋值在一条线上。显然,虽然初始化比这个更特别,因为这个代码有效。

这是标准C++吗?它是否可以跨编译器工作?我感兴趣的是如何以这种方式初始化不同于声明(使用默认ctor)然后赋值(通过在全局函数中创建的临时对象)。

UPDATE:增加了一个副本ctor和明确使用copy ctor的第三种情况。

#include <iostream> 
using namespace std; 

class TestingClass 
{ 
    public: 
    TestingClass(const TestingClass &rhs) 
    { 
     cout << "In copy ctor" << endl; 
     this->val = rhs.val + 100; 
    } 
    TestingClass(int inVal) 
    { 
     val = inVal; 
    } 

    int val; 
}; 

TestingClass testingCreator() 
{ 
    return TestingClass(100); 
} 

int main() 
{ 
    /* 
    TestingClass test1; 
    test1 = testingCreator(); 
    cout << "Test1: " << test1.val << endl; 
    */ 

    TestingClass test2 = testingCreator(); 
    cout << "Test2: " << test2.val << endl; 

    TestingClass test3(test2); 
    cout << "Test3: " << test3.val << endl; 
} 

此输出:

Test2: 100 
In copy ctor 
Test3: 200 
+0

“但是大多数人会这样认为初始化只是作为一行中的声明和赋值”......而不是大多数C++程序员。 (希望没有任何!) –

回答

2

你对TestingClass test2 = testingCreator();做什么的看法是有缺陷的。当你看到

type name = stuff; 

不创建name,然后分配给它stuff。你所做的是从stuff复制初始化name。这意味着您调用复制或移动构造函数。一般来说,这个调用可以通过优化编译器来消除,但如果不是,那么这就是你会看到的。无论哪种情况,都不会调用默认的构造函数。

在你的第一个例子

TestingClass test1; 

强制默认构造函数被调用,因为你没有一个你会得到一个错误。

+0

有趣的 - 我很清楚的复制ctor,只是不“看起来”像一个副本ctor调用 - 我通常认为这是因为当通过价值或当做更多明显的“TestingClass test2(test3);”之类的事情。很快的答案 - 谢谢! – daroo

+0

但是 - 我只是更新了代码,明确实现了一个复制ctor并在其中添加了一个打印语句。当我执行程序时,它不会打印。但是,如果我添加第三个测试“TestingClass test3(test2);”,字符串IS会打印出来。此外,我设置“this-> val = rhs.val + 100;”并且test2.val仍然被打印为100,而不是200,而test3的值打印为200. – daroo

+0

@daroo正如我所说的,编译器擅长优化此操作,即使存在副作用,副本也会被忽略,并且唯一的构造函数被称为'TestingClass(int inVal)' – NathanOliver

0

test2是由TestingClass复制构造定义,取testingCreator作为参数的结果。复制构造函数TestingClass::TestingClass(const TestingClass&)由编译器自动生成,并且C++标准保证它复制val字段。

相关问题