简体   繁体   English

重载浅拷贝和深拷贝构造函数 cpp

[英]Overload shallow and deep copy constructor cpp

I am starting with C++ environment, I hope I didn't mess up a lot with the concepts here.我是从 C++ 环境开始的,我希望我没有把这里的概念搞得一团糟。

I have one task where I need to create an object that has to be able to be copied in two ways, with a shallow copy and a deep copy.我有一项任务需要创建一个对象,该对象必须能够以两种方式进行复制,浅拷贝和深拷贝。

The object has to allow two types of copies.该对象必须允许两种类型的副本。 Either the object is shallow copied or deep copy depending on the demands.根据需求,对象是浅拷贝还是深拷贝。

In the code below I create a simple example to explain the use case.在下面的代码中,我创建了一个简单的示例来解释用例。 There, I implement the object Object with a one-argument constructor and a deep copy constructor.在那里,我用一个单参数构造函数和一个深拷贝构造函数实现了对象Object Then at some point we use the functions get_shallow and get_deep .然后在某些时候我们使用函数get_shallowget_deep

Is there a way to tell the compiler which constructor to use when it copies Object in the scope of the functions?有没有办法告诉编译器在函数范围内复制Object时使用哪个构造函数? Sometimes I will need a function to return the shallow copy and other times a deep copy.有时我需要一个函数来返回浅拷贝,有时需要一个深拷贝。

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;
}

You can use a tag on the copy constructor to indicate it is making a shallow copy.您可以在复制构造函数上使用标记来指示它正在制作浅拷贝。

Note carefully that a shallow copy does not own the resources.请注意,浅拷贝不拥有资源。 So when the owner gets destructed, any shallow copy will have dangling pointers.所以当所有者被破坏时,任何浅拷贝都会有悬空指针。 That's a very fragile situation, and easily the source of bugs.这是一个非常脆弱的情况,很容易成为错误的来源。

An alternative solution is to have a std::shared_ptr for the shared resources, and then those resources exist until all owners relinquish ownership (typically relinquishing ownership upon destruction, but could be that they change ownership over the lifecycle of the entity object).另一种解决方案是为共享资源设置一个std::shared_ptr ,然后这些资源一直存在,直到所有所有者放弃所有权(通常在销毁时放弃所有权,但也可能是他们在实体对象的生命周期内更改所有权)。

Regardless, here's an example of shallow copy constructor.无论如何,这里有一个浅拷贝构造函数的例子。

#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: using shared_ptr for the data.更新:对数据使用shared_ptr

Of course, an int as shared data is probably a bit silly.当然,将int作为共享数据可能有点傻。 But for the purposes of an example it is illustrative of whatever the data payload type.但出于示例的目的,它说明了任何数据有效负载类型。

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM