gpt4 book ai didi

c++ - 在 std::move() 之后使字符串为空的机制

转载 作者:搜寻专家 更新时间:2023-10-31 00:31:08 29 4
gpt4 key购买 nike

我对 std::move() 是如何真正清空某些东西有些困惑。

我写了一些代码:

int main()
{
string str1("this is a string");
std::cout<<std::boolalpha<<str1.empty()<<std::endl;
string str2(std::move(str1));
cout<<"str1: "<<str1.empty()<<endl;
cout<<"str2: "<<str2.empty()<<endl;
}

输出是:

true//表示原字符串为空

为什么原来的字符串每次都是清空的?我已经阅读了一些关于 move 语义的 Material ,包括它的原始建议(this one),其中说:

The difference between a copy and a move is that a copy leaves the source unchanged. A move on the other hand leaves the source in a state defined differently for each type. The state of the source may be unchanged, or it may be radically different. The only requirement is that the object remain in a self consistent state (all internal invariants are still intact). From a client code point of view, choosing move instead of copy means that you don't care what happens to the state of the source.

所以,按照这句话,上面str1的原始内容应该是某种undefined。但是为什么每次被move()后,都被清空了呢? (实际上我已经在 std::stringstd::vector 上测试了这种行为,但结果是一样的。)

为了了解更多,我定义了自己的字符串类来测试,如下所示:

class mstring
{
private:
char *arr;
unsigned size;
public:
mstring():arr(nullptr),size(0){}
mstring(char *init):size(50)
{
arr = new char[size]();
strncpy(arr,init,size);
while(arr[size-1] != '\0') //simply copy
{
char *tmp = arr;
arr = new char[size+=50]();
strncpy(arr,tmp,50);
delete tmp;
strncpy(arr-50,init+(size-50),50);
}
}

bool empty(){ return size==0;}

}

做同样的事情:

int main()
{
mstring str("a new string");
std::cout<<std::boolalpha<<str.empty()<<std::endl;
mstring anotherStr(std::move(str));
std::cout<<"Original: "<<str.empty()<<std::endl;
std::cout<<"Another: "<<anotherStr.empty()<<std::endl;
}

输出是:

original: flase//意思是原来的字符串还在

另一个:false

即使我添加了这样的 move 构造函数:

    mstring(mstring&& rvalRef)
{
*this = rvalRef;
}

结果还是一样。我的问题是:为什么 std::string 被清空而我自定义的却没有?

最佳答案

因为这就是 std::string move 构造函数的实现方式。它取得旧字符串内容的所有权(即动态分配的 char 数组),旧字符串一无所有。

另一方面,您的mstring 类实际上并未实现 move 语义。它有一个 move 构造函数,但它所做的只是使用 operator= 复制字符串。更好的实现是:

mstring(mstring&& rvalRef): arr(rvalRef.arr), size(rvalRef.size)
{
rvalRef.arr = nullptr;
rvalRef.size = 0;
}

这会将内容传输到新字符串,并使旧字符串保持默认构造函数创建它时的相同状态。这避免了分配另一个数组并将旧数组复制到其中的需要;相反,现有数组只是获得了一个新所有者。

关于c++ - 在 std::move() 之后使字符串为空的机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34782270/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com