返回值始终是临时的

Is return value always a temporary?

本文关键字:返回值      更新时间:2023-10-16

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

只有当您的程序没有将返回值复制到对象时,才会创建临时值,给出的示例是

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()构造一个局部对象。接下来,这个本地对象在调用方的堆栈上进行复制构造,生成一个temporary object,用作obj的复制构造函数的参数

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

您引用的页面是对特定编译器。形式上:返回值始终是临时的。在里面临时变量用作副本参数的上下文构造函数(对象被复制),标准给出了显式授权编译器删除副本,“合并";具有正在初始化的命名变量的临时。所有你引用的一句话是说,这个特定的编译器总是这样做他的优化(和大多数其他编译器一样)。

此页面特定于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的本地将被返回时。例如:

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
}

返回值始终是临时的。在第二种情况下,如果不能进行副本省略,则会生成该临时(在C++11中移动)的副本。