在 C++ 中想要传入函数的参数不被复制,可以通过引用或者指针的方式传入。如果说想要返回的产生也不被复制呢?当然可以直接将返回的对象作为入参以引用或者指针的形式传入,实际上直接返回也可以不复制,在C++返回参数不被复制被称为 Copy Elision

下面是一段简单的 C++ 程序,在 fun 函数厘米创建一个名为 x 的向量并将这个向量返回,然后在 main 函数中调用这个 fun 函数并将返回值赋给了 y ,第一反应这里的 y 应该是 x 的复制,也就是说在 main 中打印出来的 x 地址与 fun 中打印出来的 y 的地址应该是不一样的。

#include <vector>
#include <iostream>

std::vector<int> fun()
{
    std::vector<int> x{1, 2, 3, 4};

    std::cout << &x << std::endl;

    return x;
}


int main()
{
    std::vector<int> y = fun();

    std::cout << &y << std::endl;


    return 0;
}

但是在实际编译运行之后打印出来的结果如下,可以看到两个值是一样的

0x7ffee7ffb520
0x7ffee7ffb520

可以看到编译器在这自动优化过了,实际上 x 并没有复制一份。那么在什么情况下编译器会自动优化呢?**当返回结果上面没有判断的时候编译器会自动优化,如果存在判断编译器无法确定返回的是哪个的时候则不会优化。**可以看下面这个例子:

#include <vector>
#include <iostream>

std::vector<int> fun(int flag)
{
    std::vector<int> x{1, 2, 3, 4};

    std::cout << &x << std::endl;
    if(flag)
    {
        return {3, 4, 2, 1};
    }

    return x;
}


int main()
{
    std::vector<int> y = fun(false);

    std::cout << &y << std::endl;


    return 0;
}

在这里例子中只是加了一个 flag 参数来确定具体的返回值,传入的是 false 所以实际上程序的行为应该还是和第一个例子是一样的,但是此时打印的 xy 的地址却不一样了,也就是说 vector<int> 发生了复制

参考

  1. avoiding copy of objects with the return statement