首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重载浅、深拷贝构造函数cpp

重载浅、深拷贝构造函数cpp
EN

Stack Overflow用户
提问于 2020-11-23 15:52:39
回答 1查看 197关注 0票数 2

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

我有一个任务,我需要创建一个对象,该对象必须以两种方式被复制,一个是浅拷贝,另一个是深拷贝。

对象必须允许两种类型的副本。对象可以是浅复制的,也可以是深拷贝的,这取决于需求。

在下面的代码中,我创建了一个简单的示例来解释用例。在那里,我用一个参数构造函数和一个深拷贝构造函数实现对象Object。然后,在某个时候我们使用函数get_shallowget_deep

有没有办法告诉编译器在函数范围内复制Object时使用哪个构造函数?有时,我需要一个函数来返回浅拷贝,而其他时候则需要一个深拷贝。

代码语言:javascript
运行
复制
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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-23 16:08:41

您可以在复制构造函数上使用标记来指示它正在进行浅拷贝。

请注意,浅层副本并不拥有资源。因此,当所有者被销毁时,任何浅拷贝都会有悬挂的指针。这是一种非常脆弱的情况,也很容易成为bug的源头。

另一种解决方案是为共享资源拥有一个std::shared_ptr,然后这些资源就会存在,直到所有所有者放弃所有权为止(通常在销毁时放弃所有权,但可能会更改实体对象生命周期的所有权)。

无论如何,这里有一个浅层复制构造函数的示例。

代码语言:javascript
运行
复制
#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可能有点傻。但就一个例子而言,它说明了任何数据有效负载类型。

代码语言:javascript
运行
复制
#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
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64971731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档