C++ 如何通过值C+返回字符串+;移动语义?
我想要一个按值返回字符串的函数,并且我想要从该返回值移动构造另一个字符串。当调用NRVO/RVO时,move construktor工作正常,不进行复制,但是当我不能依赖NRVO时,函数会复制字符串,即使我显式移动返回值也是如此 我打印原始数据地址的值以检查是否进行了复制 代码如下:C++ 如何通过值C+返回字符串+;移动语义?,c++,string,copy-constructor,move-semantics,nrvo,C++,String,Copy Constructor,Move Semantics,Nrvo,我想要一个按值返回字符串的函数,并且我想要从该返回值移动构造另一个字符串。当调用NRVO/RVO时,move construktor工作正常,不进行复制,但是当我不能依赖NRVO时,函数会复制字符串,即使我显式移动返回值也是如此 我打印原始数据地址的值以检查是否进行了复制 代码如下: void printStringAdr(const std::string& s) { std::cout << (void*)s.data() << std::endl;
void printStringAdr(const std::string& s)
{
std::cout << (void*)s.data() << std::endl;
}
std::string getStringNRVO()
{
std::string str("text");
printStringAdr(str);
return str; //works fine, no copy
}
std::string getStringNoNRVO()
{
std::string str1("ABC");
std::string str2("XYZ");
if (rand() % 2)
{
printStringAdr(str1);
return str1; //makes copy
}
else
{
printStringAdr(str2);
return str2; //makes copy
}
}
std::string getStringNoNRVO_ForceMove()
{
std::string str1("ABC");
std::string str2("XYZ");
std::string* strptr = &str1;
if (rand() % 2)
strptr = &str2;
printStringAdr(*strptr);
return std::move(*strptr); //doesn't work, makes copy
}
int main()
{
std::string s = getStringNRVO(); //only this function works like i expect
printStringAdr(s);
}
void printStringAdr(const std::string&s)
{
std::您可能会在这里检测到小字符串优化。无法使用libstdc++再现这种优化;但是libstdc++使用共享(COW)字符串IIRC,因此这是不可靠的。一些字符串实现使用包含指针和缓冲区(例如8字节)的并集保存小字符串,而不是为它们分配内存。尝试使用较大的字符串,看看这是否会导致结果不正确。是的,你是正确的,我没有意识到小字符串优化。所有三个函数都可以正确处理大字符串。此外,我注意到,当strprtr被取消引用时,它需要显式移动d、 但是str1和str2不是。这是否意味着编译器在return语句中将局部值视为右值,但当对象被取消引用时,它不确定它包含什么,所以它会复制它?@vladimirm大致上是的。如果复制省略的先决条件适用于return语句,请注意返回的变量也可以是参数,编译器尝试将其视为右值(如果失败,则将其视为左值)。如果return语句中的表达式不是局部变量的名称,则前提条件不适用。