-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
可以借助解引用操作变通地对 std::unique_ptr 进行深拷贝 #32
Comments
ltimaginea
changed the title
可以借助移动操作变通地对 unique_ptr 进行深拷贝
可以借助移动操作变通地对 std::unique_ptr 进行深拷贝
Jan 7, 2022
ltimaginea
changed the title
可以借助移动操作变通地对 std::unique_ptr 进行深拷贝
可以借助解引用操作变通地对 std::unique_ptr 进行深拷贝
Feb 8, 2022
报歉,使用指针的过程中进行拷贝是不合时宜的操作。 能够进行 trivial copy 的类型没有必要用指针管理。 以下 Demo 给出了一个错误场景下使用 dereference op 进行 deep copy 的例子。 #include <iostream>
#include <memory>
// You shouldn't get an instance of it!
class UnsafeClass {
public:
virtual void do_nothing() const {
printf ("[[UNSAFE OP!!!]]\n");
}
};
class Derived : public UnsafeClass {
public:
void do_nothing() const override {
printf ("Derived: do nothing. \n");
}
};
int main() {
using namespace std;
unique_ptr < UnsafeClass > ptr = make_unique < Derived > ();
// tell me, what would happens when you call it!
ptr->do_nothing();
// do a copy!
unique_ptr < UnsafeClass > ptr2 = make_unique < decltype(ptr) :: element_type > ( *ptr );
// successfully? or not?
ptr2->do_nothing();
} |
Hi,朋友,感谢交流。 关于上条评论中,你的代码的不足之处在于:
关于多态类型的深拷贝,方法是使用设计模式中的prototype(原型模式),典型实现如下: #include <memory>
#include <typeinfo>
#include <cassert>
class Prototype
{
public:
virtual std::unique_ptr<Prototype> Clone() const = 0;
virtual ~Prototype() = default;
protected:
Prototype() = default;
// Make the polymorphic base class copy and move operations protected to prevent slicing,
// and so that only the derived class can invoke them in its own copy and move operations.
Prototype(const Prototype&) = default;
Prototype(Prototype&&) = default;
Prototype& operator=(const Prototype&) = default;
Prototype& operator=(Prototype&&) = default;
};
class Derived : public Prototype
{
public:
std::unique_ptr<Prototype> Clone() const override
{
return std::make_unique<Derived>(*this);
}
};
int main()
{
std::unique_ptr<Prototype> p = std::make_unique<Derived>();
std::unique_ptr<Prototype> q = p->Clone();
assert((p != q) && (typeid(*p) == typeid(*q)) && (typeid(*q) == typeid(Derived)));
return 0;
} See also
prototype的一个典型应用是用来实现 polymorphic_value(多态值语义),关于 polymorphic_value :
#include <iostream>
#include <vector>
#include <array>
#include <iterator>
#include <memory>
#include <utility>
#include <typeinfo>
#include <cassert>
class Shape
{
public:
std::unique_ptr<Shape> Clone() const
{
std::unique_ptr<Shape> result = DoClone();
assert(typeid(*result) == typeid(*this) && "Every derived class must correctly override DoClone.");
return result;
}
virtual void Draw() = 0;
virtual ~Shape() = default;
protected:
Shape() = default;
// Make the polymorphic base class copy and move operations protected to prevent slicing,
// and so that only the derived class can invoke them in its own copy and move operations.
Shape(const Shape&) = default;
Shape(Shape&&) = default;
Shape& operator=(const Shape&) = default;
Shape& operator=(Shape&&) = default;
private:
virtual std::unique_ptr<Shape> DoClone() const = 0;
};
class Circle : public Shape
{
public:
void Draw() override
{
std::cout << "Draw a circle." << std::endl;
}
private:
std::unique_ptr<Shape> DoClone() const override
{
return std::make_unique<Circle>(*this);
}
};
class Square : public Shape
{
public:
void Draw() override
{
std::cout << "Draw a square." << std::endl;
}
private:
std::unique_ptr<Shape> DoClone() const override
{
return std::make_unique<Square>(*this);
}
};
// a simple demo implementation of polymorphic_value
class Picture
{
public:
explicit Picture(std::unique_ptr<Shape> shape) : shape_(std::move(shape)) { }
Picture(const Picture& rhs) : shape_(rhs.shape_->Clone()) { }
Picture& operator=(const Picture& rhs)
{
if (this != &rhs)
{
shape_ = rhs.shape_->Clone();
}
return *this;
}
Picture(Picture&&) = default;
Picture& operator=(Picture&&) = default;
~Picture() = default;
void ChangeShape(std::unique_ptr<Shape> shape)
{
shape_ = std::move(shape);
}
void Draw()
{
shape_->Draw();
}
private:
std::unique_ptr<Shape> shape_;
};
int main()
{
Picture picture1(std::make_unique<Circle>());
picture1.Draw();
Picture picture2(std::make_unique<Square>());
picture2.Draw();
Picture picture3(picture1); // OK: copyable
picture3.Draw();
picture3 = picture2; // OK: copyable
picture3.Draw();
Picture picture4(std::move(picture1));
picture4.Draw();
picture4 = std::move(picture2);
picture4.Draw();
Picture picture5(std::make_unique<Circle>());
picture5.Draw();
picture5.ChangeShape(std::make_unique<Square>());
picture5.Draw();
std::vector<Picture> pictures1;
pictures1.emplace_back(std::make_unique<Circle>());
pictures1.emplace_back(std::make_unique<Square>());
for (auto& picture : pictures1)
{
picture.Draw();
}
std::vector<std::unique_ptr<Shape>> shapes1;
shapes1.push_back(std::make_unique<Circle>());
shapes1.push_back(std::make_unique<Square>());
for (auto& shape : shapes1)
{
shape->Draw();
}
std::vector<Picture> pictures2{ picture3, picture4, picture5 };
std::vector<Picture> pictures3(pictures1); // OK: copyable
std::vector<Picture> pictures4(std::move(pictures1));
pictures3 = pictures2; // OK: copyable
pictures4 = std::move(pictures2);
std::vector<std::unique_ptr<Shape>> shapes2;
shapes2.push_back(std::make_unique<Circle>());
shapes2.push_back(std::make_unique<Circle>());
shapes2.push_back(std::make_unique<Circle>());
auto init = std::to_array<std::unique_ptr<Shape>>({ std::make_unique<Circle>(), std::make_unique<Square>() });
std::vector<std::unique_ptr<Shape>> shapes3(std::make_move_iterator(init.begin()), std::make_move_iterator(init.end()));
//std::vector<std::unique_ptr<Shape>> shapes4(shapes1); // Error: noncopyable
std::vector<std::unique_ptr<Shape>> shapes5(std::move(shapes1));
//shapes3 = shapes2; // Error: noncopyable
shapes5 = std::move(shapes2);
return 0;
} 解释说明:
See also |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
CPP/week11/examples/unique_ptr.cpp
Line 56 in 8d45044
课件这里,其实可以这样进行拷贝:
std::unique_ptr<MyTime> mt3 = std::make_unique<MyTime>(*mt1);
虽然
std::unique_ptr
删除了 copy constructor 和 copy assignment operator ,但其实我们可以借助解引用操作变通地对std::unique_ptr
进行拷贝。deep copy 示例如下:
其它的例证:
The text was updated successfully, but these errors were encountered: