c++ - 重载浅拷贝和深拷贝构造函数 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
}
推荐阅读
- kotlin - Quarkus:REST 资源找不到在测试中创建的实体
- mysql - 多个datagridview数据更新到数据库mysql - vb.net
- flutter - 在小部件之外使用 GetX 观察列表
- uwp - UWP - C# / GraphicsCaptureItem 如何选择我的自我
- spring-boot - 用于启用 SSL 的 Spring Boot Cassandra 配置
- sql-server - SQl Server - Where 子句使用数据中的最大日期
- javascript - 替换特定索引处的数组元素
- javascript - Jest Mock 从一行到另一行更改为未定义
- r - mac更新后石英设备表现异常 - R mac
- javascript - 如果其他数字是奇数,则返回“偶数”,而“奇数”其他数字是偶数 javascript