Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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++ std::move-std::string-内部指针_C++_String_Move - Fatal编程技术网

C++ std::move-std::string-内部指针

C++ std::move-std::string-内部指针,c++,string,move,C++,String,Move,我很惊讶s和s2指向“sample”的内部指针不相等,这是什么解释 #include <string> #include <cassert> int main() { std::string s("sample"); std::string s2(std::move(s)); assert( reinterpret_cast<int*>(const_cast<char*>(s.data())) ==

我很惊讶s和s2指向“sample”的内部指针不相等,这是什么解释

#include <string>
#include <cassert>

int main()
{
    std::string s("sample"); 

    std::string s2(std::move(s)); 

    assert(
        reinterpret_cast<int*>(const_cast<char*>(s.data())) ==
        reinterpret_cast<int*>(const_cast<char*>(s2.data()))
        ); // assertion failure here    

    return 1;
}
#包括
#包括
int main()
{
std::字符串s(“样本”);
std::string s2(std::move(s));
断言(
重新解释强制转换(常量强制转换(s.data())==
重新解释强制转换(const强制转换(s2.data())
);//此处的断言失败
返回1;
}

为什么你认为它们应该是一样的?您正在使用其移动构造函数从
s
构造
s2
。这将数据所有权从
s
转移到
s2
,并使
s
处于“空”状态。该标准没有详细说明这需要什么,但在此之后访问
s
的数据(不首先重新分配)是未定义的

string
的简化(且不完整)版本如下所示:

class string {
    char* buffer;

public:

    string(char const* from)
        : buffer(new char[std::strlen(from) + 1])
    {
        std::strcpy(buffer, from);
    }

    string(string&& other)
        : buffer(other.buffer)
    {
        other.buffer = nullptr; // (*)
    }

    ~string() {
        delete[] buffer;
    }

    char const* data() const { return buffer; }
};

我希望这能说明
data()
成员不相等的原因。如果我们省略了
(*)
标记的行,我们将删除
main
末尾的内部缓冲区两次:一次用于
s
,一次用于
s2
。重置
buffer
指针可确保不会发生这种情况。

每个
std::string
都有自己指向的缓冲区。您从另一个移动了一个缓冲区,但这并不意味着它共享一个缓冲区。初始化
s2
时,它从
s
接管缓冲区,并成为该缓冲区的所有者。为了避免
s
拥有同一个缓冲区,它只需将
s
的缓冲区设置为一个新的空缓冲区(现在由
s
负责)

从技术上讲,还涉及到一些优化,很可能没有为空字符串或非常小的字符串显式分配真正的缓冲区,但是
std::string
的实现将使用
std::string
内存本身的一部分。这通常被称为STL中的小字符串优化


还要注意的是,
s
已被移开,因此您的代码对其数据的访问是非法的,这意味着它可能返回任何内容。

在将其值替换为某些已知值之前,您不应使用从
移动的字符串

库代码需要在参数中保留有效值,但除非类型或函数文档另有说明,否则对结果参数值没有其他约束。这意味着通常最明智的做法是避免再次使用moved-from参数。如果必须再次使用它,请确保在执行此操作之前使用已知值重新初始化它


库可以将它想要的任何东西粘贴到字符串中,但很可能最终会得到一个空字符串。这就是运行一台计算机所产生的结果。然而,人们不应该期望在“已从”对象中找到任何特别的内容。

顺便说一句,为什么要强制转换?他们什么也不做
s.data()==s2.data()
将是相同的。因为我已经开始打印地址,并在第二次切换到断言。。。忘了像你写的那样简化它