多态 r 值引用?
Polymorphic r-value references?
如果我想在 class 中存储一个多态对象,我的第一个想法是如下所示:
struct Base {
virtual void print() const {
std::cout << "Base !";
}
};
struct Derived: public Base {
void print() const {
std::cout << "Derived !";
}
};
struct PolymorphicWrapper {
std::unique_ptr<Base> base;
};
std::unique_ptr<Base>
的问题在于它会导致复杂的所有权问题和指针语义。虽然引用/原始指针可以具有多态行为,但它们不能绑定到右值。
但是我刚刚发现右值引用是多态的!!
例如:
Base && base = Derived();
base.print(); // Derived !
Base&& base2 = Base();
base2.print(); // Base !
我什至可以在 class!
中存储一个 r - 值引用
struct PolymorphicWrapper {
Base&& base;
PolymorphicWrapper(auto iBase) : base(std::move(iBase)) {} // auto to prevent object slicing
};
然而,这似乎好得令人难以置信。我在这里错过了什么吗?这是未定义行为的例子吗?
std::move
创建一个右值 reference 到一个现有的左值,它明确地将其标记为准备好从中移动。您可以从中初始化另一个右值引用,但是在特殊的生命周期延长情况下您 不是 有两个原因:
它需要一个实际的右值(即刚刚在表达式中构造并且从未通过引用传递的对象);
更重要的是,它根本不适用于引用成员。
Note: I'm reasonably sure that I've got this right, but I cannot seem to find a standard quote, probably because I'm getting lost in the aggregate initialization and temporary materialization wording. Language lawyers welcome.
因此,您只是存储了对构造函数参数的引用,该参数在所述构造函数的末尾消失并使引用悬空。
请注意,当将任意类型擦除对象存储为成员时,在一般情况下您无法避免动态分配,如果只是因为动态类型的大小未知且无界。 std::unique_ptr
是这种情况的首选,但如果您愿意,您也可以设计自己的带有小对象存储的类型擦除容器。
如果我想在 class 中存储一个多态对象,我的第一个想法是如下所示:
struct Base {
virtual void print() const {
std::cout << "Base !";
}
};
struct Derived: public Base {
void print() const {
std::cout << "Derived !";
}
};
struct PolymorphicWrapper {
std::unique_ptr<Base> base;
};
std::unique_ptr<Base>
的问题在于它会导致复杂的所有权问题和指针语义。虽然引用/原始指针可以具有多态行为,但它们不能绑定到右值。
但是我刚刚发现右值引用是多态的!!
例如:
Base && base = Derived();
base.print(); // Derived !
Base&& base2 = Base();
base2.print(); // Base !
我什至可以在 class!
中存储一个 r - 值引用struct PolymorphicWrapper {
Base&& base;
PolymorphicWrapper(auto iBase) : base(std::move(iBase)) {} // auto to prevent object slicing
};
然而,这似乎好得令人难以置信。我在这里错过了什么吗?这是未定义行为的例子吗?
std::move
创建一个右值 reference 到一个现有的左值,它明确地将其标记为准备好从中移动。您可以从中初始化另一个右值引用,但是在特殊的生命周期延长情况下您 不是 有两个原因:
它需要一个实际的右值(即刚刚在表达式中构造并且从未通过引用传递的对象);
更重要的是,它根本不适用于引用成员。
Note: I'm reasonably sure that I've got this right, but I cannot seem to find a standard quote, probably because I'm getting lost in the aggregate initialization and temporary materialization wording. Language lawyers welcome.
因此,您只是存储了对构造函数参数的引用,该参数在所述构造函数的末尾消失并使引用悬空。
请注意,当将任意类型擦除对象存储为成员时,在一般情况下您无法避免动态分配,如果只是因为动态类型的大小未知且无界。 std::unique_ptr
是这种情况的首选,但如果您愿意,您也可以设计自己的带有小对象存储的类型擦除容器。