如何解决在移动构造函数中切片对象
当变量作为 xvalue 传递给移动构造函数时,应该假设变量在执行后处于“未定义”状态;之后使用它会导致 UB。 但是,如果通过(隐式或显式)将 xvalue 转换为基类来“切片”它会发生什么?变量是否仍然部分“可用”?
示例:
#include <vector>
struct inA {
std::vector<int> s;
};
struct A {
std::vector<int> s;
A(inA&& x) : s(std::move(x.s)) { }
};
struct inB : public inA {
std::vector<char> t;
};
struct B : public A {
std::vector<char> t;
B(inB&& x) : A(std::move(x)),t(std::move(x.t)) { }
};
int main()
{
inB v{std::vector<int>(3,1),std::vector<char>(5,'a')};
B w(std::move(v));
return 0;
}
(我使用 std::vector
有一个非平凡的移动构造函数)。
A
的构造函数接受对 inA
对象的移动引用。之后移动的 inA
对象处于未定义状态且无法使用:
std::vector<int> vec{3,10};
A a(std::move(vec));
// vec[0] = 2; // UB!!
到目前为止,一切都很好。
现在,B
的构造函数可以接受对 inB
对象的移动引用,该对象派生自 inA
。
通过继承,B::B
将属于 inB&& x
的 inA
的“切片”转发给基类 A
的构造函数。然后 B::B
用不是从 inB
继承的 inA
部分初始化一个成员变量。
是否允许这最后一步(即 t(std::move(x.t))
)?
一方面,x
已经作为对 A::A
的移动引用被转发,因此它将处于未定义状态,之后使用它会导致 UB。
另一方面,A::A
不能触及成员变量 inB::t
,因为由于切片,它根本看不到它。所以我得出的结论是 inB::t
仍然可用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。