我是 C++ 的新手,想知道是否有办法在函数中创建对象,然后返回该对象而不必将其复制到内存中。我知道原始本地对象超出范围,但我希望编译器可以优化它,使对象的副本只重用相同的内存地址。
int foo()
{
int bar = 5;
std::cout << &bar << std::endl;
return bar;
}
int main()
{
char a;
auto b = foo();
std::cout << &b << std::endl;
std::cin >> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这将返回不同的内存地址。既然bar的地址不再需要,而且b的大小总是一样的,那么有什么理由不能只使用相同的地址并省去复制的步骤呢?
对于一个简单的整数并不重要,但对于更大的对象,确保返回的对象不会被复制到内存中的首选方法是什么?
以下是一个好方法吗?
int & foo(int & bar)
{
std::cout << &bar << std::endl;
// do things with bar
return bar;
}
int main()
{
char a;
auto bar = 5;
auto & b = foo(bar);
std::cout << &b << std::endl;
std::cin >> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
作为一个附带问题,为什么以下事情有效:
int & foo()
{
int bar = 5;
std::cout << &bar << std::endl;
return bar;
}
int main()
{
char a;
auto & b = foo();
std::cout << &b << " " << b << std::endl;
std::cin >> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望 bar 超出范围并且不能再被引用,但是这会编译并返回正确的值(MSVC++ 2013)。
对于简单的整数来说并不重要,但对于较大的对象来说,确保返回的对象不会在内存中复制的首选方法是什么?
只需返回对象即可。C++ 具有返回值优化,这意味着可以(并且最常见的是)省略副本:
big_object get_object()
{
big_object bo;
....
return bo;
}
....
big_object big = get_object(); // big gets built in-place
Run Code Online (Sandbox Code Playgroud)
如果您查看bo函数内部和big外部的地址,您会期望看到相同的地址(尽管 RVO 是一种可能发生的优化,但并非必须如此,因此还有其他因素可能会影响您是否看到相同的地址。使用最近的 g++ 和 clang++,我对于 size bytes 的对象获得相同的地址8,但对于 size 则不然4。)例如,这会在 clang++ 3.5 上产生相同的地址:
#include <iostream>
struct foo { int i[2]; };
foo make_foo()
{
foo f;
std::cout << &f << std::endl;
return f;
}
int main()
{
foo f = make_foo();
std::cout << &f << std::endl;
}
Run Code Online (Sandbox Code Playgroud)