首页
学习
活动
专区
圈层
工具
发布

c++11建设
EN

Stack Overflow用户
提问于 2014-01-18 18:21:20
回答 1查看 870关注 0票数 2

我正在尝试更多地了解c++,我对我的编译器正在做什么感到有点困惑。我编写了以下文件,并附有详细说明所发生情况的注释:

代码语言:javascript
复制
Test getTest()
{
    return Test(100, string("testing..."));
}

int main()
{
    // These two will call the initializer constructor...
    Test t1(5, string("hello"));
    Test t2(10, string("goodbye"));

    // This will not call operator=. This will call the copy constructor!
    Test t3 = t1;

    // This will call operator=(Test&)
    t3 = t2;

    // This will call operator=(Test&&) because rhs is an rvalue
    //   We will swap the resources in this operator= so that when getTest()
    //   deletes its resources, it will actually be deleting t3's old resources.
    //   Likewise, t3 will get getTest()'s resources.
    t3 = getTest();


    // I don't know what this is doing, but I know it's not calling the destructor.
    //   I beleive that the memory of t4 is simply what was returned by getTest().
    // Likewise with t5.
    Test t4(getTest());
    Test* t5 = new Test(getTest());

    Test t6(t4);

    return 0;
}

t4和t5似乎没有输入任何构造函数,实际上只是使用getTest()分配的内存。我假设t4会输入rValue复制构造函数: Test(const && rhs),但即使它的参数是rValue,它也不会。Test t4(getTest())不调用任何析构函数,因此我假设t4只是获取内存。t6确实调用了复制构造函数。

我查看了Visual 2013中的程序集代码,发现了以下内容:

代码语言:javascript
复制
    Test t4(getTest());
00F59B8C  push        8  
00F59B8E  lea         ecx,[t4]  
00F59B91  call        Test::__autoclassinit2 (0F51285h)  
00F59B96  lea         eax,[t4]  
00F59B99  push        eax  
00F59B9A  call        getTest (0F51456h)  
00F59B9F  add         esp,4  
00F59BA2  mov         byte ptr [ebp-4],8  

因此,它看起来像是调用了一个名为autoclassinit2的东西,然后从getTest获取内存,最后将它存储在t4中?

所以我想我的问题是:这仅仅是一个编译器优化,直接将getTest()中的构造函数的内存分配给t4吗?使用getTest() 2.调用rVal复制构造函数3.破坏getTest()内存?还是这里还发生了什么事?谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-18 19:49:27

声明中的=的意思是‘隐式构造请’(基本上),而不是'call operator=‘。

C++有一个被称为省略的概念。省略的意思是“使两个或多个变量成为相同的事物”。关于编译器什么时候可以这样做,有一些规则。与其他优化不同,即使有副作用,它也是合法的。

如果使用相同类型的未命名临时变量初始化变量,则编译器可以删除该临时变量。如果从函数返回局部变量,则可以(在某些情况下)将其省略到未命名的返回值中。临时人员的匿名返回也是如此。NRVO和RVO是您想要的关键字。

在许多情况下,如果省略由于技术原因或编译器限制而失败,则会隐式地发生move。然而,显式move阻止省略。因此,了解规则对于流血边缘优化代码非常重要。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21208027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档