C++ 复制省略和右值引用
在下面的代码中,使用什么来避免复制、省略或右值引用和移动构造函数C++ 复制省略和右值引用,c++,c++11,C++,C++11,在下面的代码中,使用什么来避免复制、省略或右值引用和移动构造函数 std::string get(){return "...";} void foo(std::string var){} foo( get() ); //<--- here std::string get(){return“…”;} void foo(std::string var){} foo(get())// 已定义实现,但很可能是复制省略 类似地,当从函数返回对象值时,RVO/NRVO很可能在移动语义之前生效 s
std::string get(){return "...";}
void foo(std::string var){}
foo( get() ); //<--- here
std::string get(){return“…”;}
void foo(std::string var){}
foo(get())// 已定义实现,但很可能是复制省略
类似地,当从函数返回对象值时,RVO/NRVO很可能在移动语义之前生效
std::string get(){
// this is similar to return std::string("..."), which is
// copied/moved into the return value object.
return "...";
}
RVO允许它将临时字符串对象直接构造到get()
的返回值对象中
RVO允许它直接将临时字符串对象(返回值对象)构造到foo
的参数对象中
这些是允许的RVO场景。如果编译器无法应用它们,则必须使用移动构造函数(如果可用)将返回值分别移动到返回值对象和参数对象中。在这种情况下,这并不奇怪,因为两个临时对象都被视为或被视为右值。(对于第一个场景,没有表达式对应于创建的临时对象,因此处理仅用于选择用于将临时对象复制/移动到返回值对象中的构造函数)
对于其他情况,编译器必须将事物视为rValk,即使它们是LValue/P>
std::string get(){
std::string s = "...";
// this is similar to return move(s)
return s;
}
该规范指出,当它可能根据规定的规则将RVO(或NRVO)应用于左值时,需要实现将表达式视为右值并使用移动构造函数(如果可用),并且只有在找不到合适的构造函数时,才应将表达式作为左值使用。对于程序员来说,在这种情况下编写显式的移动是很遗憾的,因为很明显,程序员总是希望移动而不是复制
例如:
struct A { A(); A(A&); };
struct B { B(); B(B&&); };
A f() { A a; return a; }
B f() { B b; return b; }
对于第一种情况,它将a
作为右值,但找不到接受此右值的构造函数(a&
无法绑定到右值)。因此,它再次将a
视为它是什么(左值)。对于第二个,它将b
作为右值,并使b(b&&)
获取该右值并移动它。如果它将b
作为左值(它是什么),那么复制初始化将失败,因为b
没有隐式声明复制构造函数
请注意,返回和参数传递使用复制初始化规则,这意味着
u -> T (where u's type is different from T) =>
T rvalue_tmp = u;
T target(rvalue_tmp);
t -> T (where t's type is T) =>
T target = t;
因此,在返回“…”
的示例中,我们首先创建一个临时右值,然后将其移动到目标中。对于返回返回值/参数类型的表达式的情况,我们将直接将该表达式移动/复制到目标中 最有可能是复制省略,但如果编译器无法在这种情况下应用(如果函数更复杂,可能会发生这种情况),那么您正在考虑移动。移动非常有效,所以如果不执行省略,我不会在这里惊慌失措
u -> T (where u's type is different from T) =>
T rvalue_tmp = u;
T target(rvalue_tmp);
t -> T (where t's type is T) =>
T target = t;