我是从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;
}
发布于 2020-11-23 16:08:41
您可以在复制构造函数上使用标记来指示它正在进行浅拷贝。
请注意,浅层副本并不拥有资源。因此,当所有者被销毁时,任何浅拷贝都会有悬挂的指针。这是一种非常脆弱的情况,也很容易成为bug的源头。
另一种解决方案是为共享资源拥有一个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";
}
UPDATE:对数据使用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
}
https://stackoverflow.com/questions/64971731
复制相似问题