2012-05-11 42 views
3

我试图理解这种分配在C是如何工作++:C++简单的分配由函数

Test other = toto(); 

这是一个完整的代码来源:

#include <iostream> 

class Test 
{ 
public: 
    Test() 
    { 
     j = i++; 
     std::cout<<"default constructor "<<j<<std::endl; 
    } 

    Test(const Test&) 
    { 
     std::cout<<"constuctor by copy "<<j<<std::endl; 
    } 
    Test & operator=(const Test&) 
    { 
     std::cout<<"operator = "<<j<<std::endl; 
     return *this; 
    } 
    int j; 
    static int i; 
}; 

int Test::i = 0; 

Test toto() 
{ 
    Test t; 
    return t; 
} 

int main() 
{ 
    Test other = toto(); 
    std::cout<<other.j<<std::endl; 
    Test another; 
    return 0; 
} 

的代码不会被复制或操作员使用的构造=,所以我不明白它有多么的作品...... 我用gcc 4.7.0

Thranks您的帮助:)

杰罗姆

+0

@jrok - 从FAQ“他们的一位工程师告诉我,他们发现这个回报率按价值优化是如此之快,你得到它,即使你不打开优化编译”,因此显然这不是一定是真的。它可能因编译器而异。 – Benj

+0

@Benj事实上,在使用gcc进行尝试的情况下,即使没有优化也没有副本。 – jrok

回答

7

的格式语义:

Test other = toto(); 

涉及多个副本(但没有分配)。编译器允许 elide所有不同的实例,但是,这消除了 副本;几乎所有的编译器都会做这种优化。

更具体地说,标准没有指定返回类类型 的值,但通常的解决方案是调用者分配 空间,并将隐藏指针传递给函数。如果没有 上述mentionned优化:

Test 
toto() 
{ 
    Test t; 
    return t; 
} 

会导致局部变量t正在建设中,那么 return语句会被隐藏 指针复制t进入空间指向。优化(称为命名返回值优化,或 NRVO)使用的空间指向的 隐藏指针t,而不是创建一个单独的t局部这里导致编译器。 (显然,它这样做的时候,它自毁t,复制后否则,因为它会 。)

在宣言:

Test t = toto(); 

,形式语义将有编译器分配用于一个 临时型测试的空间,通过这个空间的地址作为隐藏 指针toto,然后复制该临时成t和破坏它。 这里的优化包括编译器的 t地址通过直接toto,eliding中间预。