我有一个大班,拿着很多STL容器.
编译器会自动创建一个移动构造函数来将这些容器移动到目标,还是我必须自己创建?
我想定义一个用于编组数据的类; 当编组完成后,我想move从其中输出编组数据,这可能会使编组对象无效.
我相信这可以通过以下static功能实现extractData:
class Marshaller
{
public:
static DataType extractData(Marshaller&& marshaller)
{
return std::move(marshaller.data);
}
private:
DataType data;
}
Run Code Online (Sandbox Code Playgroud)
这有点不方便打电话,但是:
Marshaller marshaller;
// ... do some marshalling...
DataType marshalled_data{Marshaller::extractData(std::move(marshaller))};
Run Code Online (Sandbox Code Playgroud)
那么我可以用成员函数包装它吗?
DataType Marshaller::toDataType()
{
return Marshaller::extractData(std::move(*this));
}
Run Code Online (Sandbox Code Playgroud)
当然,这将使用以下方式调用:
DataType marshalled_data{marshaller.toDataType()};
Run Code Online (Sandbox Code Playgroud)
...对我来说,看起来更好.但那std::move(*this)件事看起来非常可疑.在调用的上下文中toDataType(),marshaller不能再次使用,但我不认为编译器可以知道:函数体可能在调用者的编译单元之外,所以没有什么可以表明marshaller已经move()应用于它.
这是未定义的行为吗?它完全没问题吗?还是介于两者之间?有没有更好的方法来实现相同的目标,最好不使用宏或要求调用者明确move marshaller?
编辑:使用G ++和Clang ++,我发现我不仅可以编译上面的用例,而且我实际上可以继续通过编组器对底层数据进行修改,然后使用该toDataType函数重新提取修改后的数据.我还发现已经提取的数据marshalled_data继续被更改marshaller,这表明它在调用上下文marshalled_data之间共享marshaller,所以我怀疑存在内存泄漏或未定义的行为(来自双删除) .
编辑2: …
我目前正试图弄清楚如何使用包含指向已分配内存的指针的对象正确地移动语义.我有一个大的数据结构,其中包含一个指向实际存储的内部原始指针(出于效率原因).现在我添加了一个移动构造函数并移动operator=().在这些方法中,我是std::move()指向新结构的指针.但是我不知道如何处理来自其他结构的指针.
这是我正在做的一个简单的例子:
class big_and_complicated {
// lots of complicated code
};
class structure {
public:
structure() :
m_data( new big_and_complicated() )
{}
structure( structure && rhs ) :
m_data( std::move( rhs.m_data ) )
{
// Maybe do something to rhs here?
}
~structure()
{
delete m_data;
}
private:
big_and_complicated * m_data;
}
int main() {
structure s1;
structure s2( std::move( s1 ) );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在从我的理解,std::move( s1 )到s2唯一可以安全做的事情就是s1调用它的构造函数.但是据我所知,这将导致删除s1 …