簡體   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