gpt4 book ai didi

c++ - std::move 更改变量地址?

转载 作者:行者123 更新时间:2023-11-30 01:09:55 25 4
gpt4 key购买 nike

我发现了意外的(至少对我而言)行为。

class A
{
char _text[100];
char* _beg;
char* _end;
public:
explicit A(char* text, size_t tsize) : _beg(&text[0]), _end(&text[std::min(tsize, 99)])
{
memcpy(_text, text, std::min(tsize, 99));
*_end = '\0';
}
inline std::string get_text()
{
return std::move(std::string(_beg, _end));
}
};

在那之后我在代码的某处这样做:

  A* add_A(A&& a)
{
list_a.push_back(std::move(a));
return &(list_a.back());
}

std::list<A> list_a;
{
add_A(A("my_text", 7));
list_a.back().get_text(); //returns "my_text"
}
list_a.back().get_text(); //returns trash

因为只有我 move 这个类(使用std::move),并调用被 move 对象的get_text(),我得到垃圾,就像 move 后一样变量 _text 的地址改变了,因此 _beg_end 指向任何地方。

std::move 之后变量的地址真的可以改变吗(我认为 move 并没有真正 move 对象,它就是为此而发明的)?

如果它可以改变,处理它的通常模式是什么(相应地改变指针)?

如果它不能改变,可能会发生这种行为,因为我试图将这样的对象 move 到 std::list (因此不知何故发生了复制,它改变了变量的地址并制作指针指向错误的位置)?

最佳答案

C++ 中的 move 只是一种特殊形式的复制,您可以在其中修改要 move 的对象中的数据。 unique_ptr 就是这样工作的;您将指针从一个 unique_ptr 对象复制到另一个对象,然后将原始值设置为 NULL。

当您 move 一个对象时,您正在创建一个新对象,一个从另一个对象获取数据的对象。成员(member)地址不“变”;这只是不同的对象

因为您没有编写复制/move 构造函数,这意味着编译器会为您编写一个。他们所做的就是复制每个元素。因此,新 move 到的对象将具有指向旧对象的指针。。

即将被销毁的对象。

这就像搬进一栋恰好与旧房子一模一样的房子。无论它看起来多么像你的老房子,它都不是。你还是得改地址,因为是新房子。 _beg_end 的地址也必须更新。

现在,您可以创建一个 move 构造函数/赋值运算符(以及一个复制构造函数/赋值运算符)来更新您的指针。但坦率地说,这只是糟糕设计的装饰。如果可以的话,在同一个对象中使用指向子对象的指针并不是一个好主意。而不是开始/结束指针,只有一个实际的大小:

class A
{
char _text[100];
size_t _size;
public:
explicit A(char* text, size_t tsize) : _size(tsize)
{
strncpy(_text, text, 100);
}
inline std::string get_text()
{
return std::string(_text, _size); //Explicit `move` call is unnecessary
}
};

这样,就不需要存储开始/结束指针。这些可以根据需要合成。

关于c++ - std::move 更改变量地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39192579/

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