微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在移动构造函数中切片对象

如何解决在移动构造函数中切片对象

当变量作为 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&& xinA 的“切片”转发给基类 A 的构造函数。然后 B::B 用不是从 inB 继承的 inA 部分初始化一个成员变量。

是否允许这最后一步(即 t(std::move(x.t)))?

一方面,x 已经作为对 A::A 的移动引用被转发,因此它将处于未定义状态,之后使用它会导致 UB。

另一方面,A::A 不能触及成员变量 inB::t,因为由于切片,它根本看不到它。所以我得出的结论是 inB::t 仍然可用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。