[英]Overload shallow and deep copy constructor cpp
我是从 C++ 环境开始的,我希望我没有把这里的概念搞得一团糟。
我有一项任务需要创建一个对象,该对象必须能够以两种方式进行复制,浅拷贝和深拷贝。
该对象必须允许两种类型的副本。 根据需求,对象是浅拷贝还是深拷贝。
在下面的代码中,我创建了一个简单的示例来解释用例。 在那里,我用一个单参数构造函数和一个深拷贝构造函数实现了对象Object
。 然后在某些时候我们使用函数get_shallow
和get_deep
。
有没有办法告诉编译器在函数范围内复制Object
时使用哪个构造函数? 有时我需要一个函数来返回浅拷贝,有时需要一个深拷贝。
using namespace std;
class Object;
typedef std::shared_ptr<Object> objectPtr;
class Object{
private:
int *data;
public:
Object(int d);
Object(const Object &source);
~Object();
};
// One argument constructor
Object::Object(int d) {
data = new int;
*data = d;
}
//deep copy constructor
Object::Object(const Object &source) :Object(*source.data) {}
Object::~Object() {delete data;}
Object get_shallow(Object object) {
return object;
}
Object get_deep(Object object) {
return object;
}
int main(){
Object object1 {100};
get_deep(object1); //returns a deep copy of the object
get_shallow(object1); //returns a shallow copy of the object
return 0;
}
您可以在复制构造函数上使用标记来指示它正在制作浅拷贝。
请注意,浅拷贝不拥有资源。 所以当所有者被破坏时,任何浅拷贝都会有悬空指针。 这是一个非常脆弱的情况,很容易成为错误的来源。
另一种解决方案是为共享资源设置一个std::shared_ptr
,然后这些资源一直存在,直到所有所有者放弃所有权(通常在销毁时放弃所有权,但也可能是他们在实体对象的生命周期内更改所有权)。
无论如何,这里有一个浅拷贝构造函数的例子。
#include <iostream>
using std::cout;
using std::ostream;
class Object {
int* data;
bool delete_data = true;
public:
enum Shallow_tag { shallow };
~Object();
Object(int d);
Object(Object const&); // DEEP copy.
Object(Object const&, Shallow_tag); // SHALLOW copy.
bool is_shallow() const { return !delete_data; }
auto get_data() const -> int* { return data; }
};
Object::~Object() { if (delete_data) delete data; }
// One argument constructor
Object::Object(int d) : data{new int(d)} { }
//deep copy constructor
Object::Object(Object const& other) : Object(*other.data) {}
// shallow copy
Object::Object(Object const& other, Shallow_tag) : data{other.data}, delete_data{false} {}
Object get_shallow(Object const& object) {
return Object(object, Object::shallow);
}
Object get_deep(Object object) {
return object;
}
ostream& operator<<(ostream& out, Object const& obj) {
out << (obj.is_shallow() ? "shallow" : "deep") << " ";
auto d = obj.get_data();
if (d) out << "data:" << *d;
else out << "data:(null)";
return out;
}
int main() {
auto object1 = Object{100};
auto obj2 = get_deep(object1); //returns a deep copy of the object
auto obj3 = get_shallow(object1); //returns a shallow copy of the object
cout << "obj2 is " << obj2 << "\n";
cout << "obj3 is " << obj3 << "\n";
}
更新:对数据使用shared_ptr
。
当然,将int
作为共享数据可能有点傻。 但出于示例的目的,它说明了任何数据有效负载类型。
#include <iostream>
#include <memory>
using std::cout;
using std::make_shared;
using std::ostream;
using std::shared_ptr;
class Object {
shared_ptr<int> data;
public:
Object(int d);
auto get_data() const -> int* { return data.get(); }
};
Object::Object(int d) : data{make_shared<int>(d)} { }
auto operator<<(ostream& out, Object const& obj) -> ostream& {
auto d = obj.get_data();
if (d) out << "data:" << *d;
else out << "data:(null)";
return out;
}
Object get_copy(Object o) {
return o;
}
int main() {
auto object1 = Object{100};
auto obj2 = get_copy(object1);
auto obj3 = get_copy(object1);
cout << "obj2 is " << obj2 << "\n"; // 100
cout << "obj3 is " << obj3 << "\n"; // 100
*object1.get_data() = 5;
cout << "obj2 is " << obj2 << "\n"; // 5
cout << "obj3 is " << obj3 << "\n"; // 5
obj2 = Object{75};
cout << "obj2 is " << obj2 << "\n"; // 75
cout << "obj3 is " << obj3 << "\n"; // 5
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.