繁体   English   中英

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

[英]Overload shallow and deep copy constructor cpp

我是从 C++ 环境开始的,我希望我没有把这里的概念搞得一团糟。

我有一项任务需要创建一个对象,该对象必须能够以两种方式进行复制,浅拷贝和深拷贝。

该对象必须允许两种类型的副本。 根据需求,对象是浅拷贝还是深拷贝。

在下面的代码中,我创建了一个简单的示例来解释用例。 在那里,我用一个单参数构造函数和一个深拷贝构造函数实现了对象Object 然后在某些时候我们使用函数get_shallowget_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.

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