3

这个页面说了一件奇怪的事情:-

仅当您的程序不将返回值复制到对象时才会创建临时对象,并且给出的示例是

UDT Func1(); // Declare a function that returns a user-defined type.
            ...

Func1();        //  Call Func1, but discard return value.
               //  A temporary object is created to store the return
              //   value

但如果我已经完成了:-

UDT obj=Fuct1;

在我看来,它还将创建一个临时文件,如下所示:-

Func()构造一个本地对象。接下来,在调用者的堆栈上复制构造这个本地对象,将 atemporary object用作 obj 的复制构造函数的参数。

我错了吗?
这与复制省略有关吗?

4

3 回答 3

5

您引用它的页面描述了特定编译器的行为。形式上:返回值始终是临时的。在将该临时值用作复制构造函数的参数(对象被复制)的上下文中,该标准明确授权编译器删除副本,将临时值与它正在初始化的命名变量“合并”。你引用的所有句子都是说这个特定的编译器总是做他的优化(就像大多数其他编译器一样)。

于 2012-01-27T08:35:52.870 回答
4

此页面是 Microsoft 特定的。确实,标准允许在函数返回期间对复制构造函数进行两次、一次或零次调用(这称为复制省略)。事实上,一个电话就足够了。

假设你写:

A f(int x) {
    return A(x);
}

void g() {
    A r = f(10);
}

MSVC 实现这一点的方式是:

void f_impl(A* r, int x) {
    new((void*)r) A(x); // construct the return value into r
}

void g_impl() {
    A r = __uninitialized__;
    f_impl(&r, 10);
}

在这里,您看到对复制构造函数的调用为零,并且没有临时对象。

如果你f这样打电话:

void g() {
    f(10);
}

然后编译器仍然需要在某处构造返回值,所以它创建了一个临时的:

void g_impl() {
    A r = __uninitialized__;
    f_impl(&r, 10);
    r.~A(); // destruct temporary
}

什么时候调用复制构造函数?在执行f时不知道f会返回哪个'local'。例如这个:

A f(int x)
{
    A r1;
    A r2;
    // ...do something complicated modifying both r1 and r2...
    if(x)
        return r1;
    // ...do something complicated...
    return r2;
}

被翻译成这样的东西:

void f_impl(A* r, int x)
{
    A r1;
    A r2;
    // ...do something complicated modifying both r1 and r2...
    if(x)
    {
        new((void*)r) A(r1); // copy construct r1
        return;
    }
    // ...do something complicated...
    new((void*)r) A(r2); // copy construct r2
}
于 2012-01-27T08:32:42.463 回答
0

返回值始终是临时的。在第二种情况下,如果复制省略不会发生,则制作该临时文件的副本(在 C++11 中移动)。

于 2012-01-27T05:38:42.203 回答