Mah*_*koe 2 c++ stdvector move-semantics
我的C ++代码中有一个具有自己的move构造函数的类。此处显示了简化版本:
class myClass {
//In this example, myClass must manually manage allocating
//and freeing a memory buffer.
char *mem;
//...
//Regular constructor, copy constructor, etc
//...
myClass(myClass &&other) {
//Swap our memory pointer with other's memory pointer
char *tmp = other.mem;
other.mem = mem;
mem = tmp;
}
//...
//Destructor, other member functions, etc.
//...
}
Run Code Online (Sandbox Code Playgroud)
在正常情况下,这可以正常工作。但是,最近我需要对这些对象进行向量处理:
vector<myClass> v;
v.reserve(10); //Make space, but do not construct
v.push_back(myClass()); //Problem!
Run Code Online (Sandbox Code Playgroud)
在经历了段错误并逐步使用gdb之后,我最终发现应该是显而易见的:如果尝试从右值引用构造对象,则可能导致在未初始化的内存上使用move构造函数。
当您有可能将垃圾交换到other类中时,应该如何编写move构造函数?有什么方法可以检测到这一点吗?
当您有可能将垃圾交换到另一个类中时,应该如何编写move构造函数?有什么方法可以检测到这一点吗?
未初始化的对象将保留不确定的值,直到为其分配了另一个值[basic.indet] / 1为止。基本上,除了为对象分配适当的值[basic.indet] / 2之外,基本上不允许对它具有不确定的值。由于您甚至不被允许查看对象持有的值,除非对象已被初始化或分配了值,所以不可能仅通过查看对象本身来检测对象是否已初始化(因为您已经甚至不允许看)。因此,严格来说,实际上,您并不仅仅是在“将垃圾值交换到另一个类中”,而是在调用未定义的行为。交换垃圾就是这种未定义行为通常表现出来的方式。
该问题的解决方案很简单:确保始终将指针初始化为有效值,例如nullptr:
class myClass {
//In this example, myClass must manually manage allocating
//and freeing a memory buffer.
char *mem = nullptr;
//...
//Regular constructor, copy constructor, etc
//...
myClass(myClass &&other) {
//Swap our memory pointer with other's memory pointer
char *tmp = other.mem;
other.mem = mem;
mem = tmp;
}
//...
//Destructor, other member functions, etc.
//...
}
Run Code Online (Sandbox Code Playgroud)
与其自己实现move构造函数,不如考虑仅使用type的成员std::unique_ptr并仅依靠隐式定义的move构造函数。例如:
class myClass
{
std::unique_ptr<char[]> mem;
// regular constructor, copy constructor, etc.
myClass(myClass&&) = default;
// other member functions, etc.
};
Run Code Online (Sandbox Code Playgroud)