Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过值C+返回字符串+;移动语义?_C++_String_Copy Constructor_Move Semantics_Nrvo - Fatal编程技术网

C++ 如何通过值C+返回字符串+;移动语义?

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;

我想要一个按值返回字符串的函数,并且我想要从该返回值移动构造另一个字符串。当调用NRVO/RVO时,move construktor工作正常,不进行复制,但是当我不能依赖NRVO时,函数会复制字符串,即使我显式移动返回值也是如此

我打印原始数据地址的值以检查是否进行了复制

代码如下:

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语句中的表达式不是局部变量的名称,则前提条件不适用。