在下面的代码中,使用了什么来避免复制、省略或右值引用和移动构造函数?
std::string get(){return "...";}
void foo(std::string var){}
foo( get() ); //<--- here发布于 2011-04-15 17:58:04
std::string get(){
// this is similar to return std::string("..."), which is
// copied/moved into the return value object.
return "...";
}RVO允许它将临时字符串对象直接构造到get()的返回值对象中。
foo( get() );RVO允许它直接将临时字符串对象(返回值对象)直接构造到foo的参数对象中。
这些是允许的RVO场景。如果编译器无法应用它们,则必须使用移动构造函数(如果可用)将返回值分别移动到返回值对象和参数对象中。在这种情况下,这并不奇怪,因为这两个临时对象都被视为或被视为右值。(对于第一个场景,没有与创建的临时对象相对应的表达式,因此处理的目的只是为了选择使用哪个构造函数将临时对象复制/移动到返回值对象中)。
对于其他情况,编译器必须将事物视为右值,即使它们是左值。
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;因此,在返回"..."的示例中,我们首先创建一个临时右值,然后将其移动到目标中。对于返回返回值/参数类型的表达式的情况,我们将直接将该表达式移动/复制到目标中。
发布于 2011-04-15 20:11:27
最有可能的是复制ellision,但是如果你的编译器在这种情况下不能应用,如果函数更复杂就会发生这种情况,那么你就是在考虑移动。移动是非常有效的,所以如果没有执行ellision,我不会在这里感到恐慌。
发布于 2011-04-15 17:48:08
实现已定义,但最有可能是复制省略。
类似地,当从函数返回对象值时,RVO/NRVO很可能会在移动语义之前生效。
https://stackoverflow.com/questions/5674983
复制相似问题