我很惊讶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;
}发布于 2013-04-07 19:03:55
为什么你认为它们应该是一样的呢?您正在使用s的move构造函数从它构造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指针可以确保这种情况不会发生。
发布于 2013-04-07 19:04:23
每个std::string都有它自己指向的缓冲区。您将一个从另一个移动到另一个并不会使它共享一个缓冲区。初始化s2时,它将从s手中接管缓冲区并成为该缓冲区的所有者。为了避免s“拥有”相同的缓冲区,它简单地将s的缓冲区设置为一个新的空缓冲区(现在由s负责)。
从技术上讲,也涉及到一些优化,很可能没有一个真正的缓冲区显式地分配给空字符串或非常小的字符串,但是std::string的实现将使用std::string本身的一部分内存,这通常被称为STL语言中的小字符串优化。
还要注意,s已经被移走了,所以你的代码访问它的数据是非法的,这意味着它可能会返回任何东西。
发布于 2013-04-07 19:05:04
在将其值替换为某个已知值之前,不应使用moved-from string:
库代码需要在参数中保留一个有效值,但除非类型或函数另有说明,否则对得到的参数值没有其他约束。这意味着通常最明智的做法是避免再次使用moved from参数。如果必须再次使用它,请确保在执行此操作之前使用已知值重新初始化它。
库可以将它想要的任何内容插入到字符串中,但很可能最终得到的是一个空字符串。这就是运行example from cppreference所产生的结果。然而,人们不应该期望在一个移出的对象中找到任何特别的东西。
https://stackoverflow.com/questions/15861620
复制相似问题