C++11 是否有可能拥有一个可复制的可构造类来保存std::unique\u ptr<;基地>;避免在不暴露基底的情况下进行切片;克隆;功能?
有没有一种方法可以为类(例如,C++11 是否有可能拥有一个可复制的可构造类来保存std::unique\u ptr<;基地>;避免在不暴露基底的情况下进行切片;克隆;功能?,c++11,copy-constructor,smart-pointers,move-semantics,deep-copy,C++11,Copy Constructor,Smart Pointers,Move Semantics,Deep Copy,有没有一种方法可以为类(例如,Copyable)编写一个复制构造函数,该类将std::unique_ptr保存到基类(但实际上是存储派生的对象) 快速测试显示出现了预期的切片,因为Copyable不知道它所持有的实际类型。因此我认为需要一个clone方法,但我想知道是否有一种方法可以让编译器以更好的方式处理这个问题 切片代码: #include <algorithm> #include <iostream> #include <memory> struct B
Copyable
)编写一个复制构造函数,该类将std::unique_ptr
保存到基
类(但实际上是存储派生的
对象)
快速测试显示出现了预期的切片,因为Copyable
不知道它所持有的实际类型。因此我认为需要一个clone
方法,但我想知道是否有一种方法可以让编译器以更好的方式处理这个问题
切片代码:
#include <algorithm>
#include <iostream>
#include <memory>
struct Base
{
Base(int i = 0) : i(i) {}
virtual ~Base() = default;
int i;
virtual int f() { return i; }
};
struct Derived : Base
{
Derived() = default;
virtual int f() override { return 42; }
};
struct Copyable
{
Copyable(std::unique_ptr<Base>&& base) : data(std::move(base)) {}
Copyable(const Copyable& other)
{
data = std::make_unique<Base>(*other.data);
}
std::unique_ptr<Base> data;
};
int main()
{
Copyable c(std::make_unique<Derived>());
Copyable c_copy = c;
std::cout << c_copy.data->f() << '\n';
}
显然,克隆代码是有效的。问题是,其中有些东西我想避免:
新
注:出于所有明显的原因,我想使用智能指针,我只需要一个深度复制
std::unique_ptr
。类似于std::copyable_unique_ptr
,将可选移动语义与深度复制构造函数相结合。这是最干净的方法吗?还是只会增加混乱?您当然可以创建一个clone\u ptr
-为静态地知道如何克隆的任何对象初始化
它将包含一个指向对象的指针,以及一个指向用于克隆所述对象的函数的指针,可能来自转换无状态lambda。您当然可以为静态地知道如何克隆的任何对象创建一个
clone\u ptr
-类
它将包含一个指向对象的指针,以及一个指向用于克隆所述对象的函数的指针,可能来自转换无状态lambda。a
std::copyable_unique_ptr
没有意义。拥有一个指向可克隆对象的std::unique_ptr
更有意义。您拥有的可能是最好的方法。有不过有两点:复制构造函数是一个构造函数,因此它可以有一个成员初始化列表。clone
函数应该调用复制构造函数,复制*这个
。派生类中的clone
函数应该返回一个指向基类的指针。@Someprogrammerdude可复制函数如何运行ique_ptr
毫无意义?有很多情况下,双方都希望在需要时移动和复制数据。当然,您需要小心使用std::move
,但复制仅移动的类型而不弄脏接口似乎意味着这是一个明智的解决方案。@rubenvb复制构造的危险当用户不希望调用TOR时,调用TOR是不赞成使用auto\u ptr
的一个重要原因。使用copyable\u unique\u ptr
,效果会稍微好一点,但仍然不好。clonable\u unique\u ptr
(或clone\u ptr
,就像重复数据消除程序的答案一样)它不提供复制构造函数,但提供了clone()
member函数,实现了您希望通过copyable\u unique\u ptr
实现的功能,但没有危险。发生深度复制而不是移动的危险?我更喜欢使用copyable\u unique\u ptr
生成类的默认复制/移动构造函数,而不是单独的克隆函数。但我同意这是一个折衷。嗯,似乎不可能让一个copyable\u unique\u ptr
正确地创建一个副本,而它的指针实际上是派生的。一个std::copyable\u unique\u ptr
没有意义。有一个指向可克隆对象的std::unique\u ptr
更有意义。你拥有的可能是最好的方法。有一个耦合但是要点之一:复制构造函数是一个构造函数,因此它可以有一个成员初始化列表。clone
函数应该调用复制构造函数,复制*这个。派生类中的clone
函数应该返回一个指向基类的指针。@Someprogrammerdude可复制函数如何唯一_ptr
毫无意义?在很多情况下,双方都希望在需要时移动和复制数据。当然,您需要小心使用std::move
,但复制仅移动的类型而不弄脏接口似乎意味着这是一个明智的解决方案。@rubenvb复制构造函数的危险性在用户不期望的情况下被调用是auto\u ptr
被弃用的一个重要原因。使用copyable\u unique\u ptr
,效果会稍微好一点,但仍然不好。clonable\u unique\u ptr
(或clone\u ptr
与重复数据消除程序的答案一样)它不提供复制构造函数,但提供了clone()
member函数,实现了您希望通过copyable\u unique\u ptr
实现的功能,但没有危险。发生深度复制而不是移动的危险?我更喜欢使用copyable\u unique\u ptr
生成类的默认复制/移动构造函数,而不是单独的克隆函数。但我同意这是一个折衷。嗯,似乎不可能让可复制的\u unique\u ptr
在其指针实际是派生的
时正确创建副本。
#include <algorithm>
#include <iostream>
#include <memory>
struct Base
{
Base(int i = 0) : i(i) {}
virtual ~Base() = default;
int i;
virtual int f() { return i; }
virtual Base* clone() { return new Base(i); }
};
struct Derived : Base
{
Derived() = default;
virtual int f() override { return 42; }
virtual Derived* clone() override { return new Derived(); }
};
struct Copyable
{
Copyable(std::unique_ptr<Base>&& base) : data(std::move(base)) {}
Copyable(const Copyable& other)
{
data.reset(other.data->clone());
}
std::unique_ptr<Base> data;
};
int main()
{
Copyable c(std::make_unique<Derived>());
Copyable c_copy = c;
std::cout << c_copy.data->f() << '\n';
}