【问题标题】:C++ Destructors and OwnershipC++ 析构函数和所有权
【发布时间】:2020-02-15 13:52:39
【问题描述】:

我尝试在我的 c 编程中复制 C++ 析构函数和构造函数。这意味着对于每个对象或结构,都有一个初始化函数和一个析构函数,它们可以像这样释放所有对象资源:

struct MyObject {
      struct string a;
      struct string b;
      struct string c;
};

ConstructMyObject(struct MyObject *obj) {
     ConstructString(&obj->a);
     ConstructString(&obj->b);
     ConstructString(&obj->c);
}

DestructMyObject(struct MyObject *obj) {
     DestructString(&obj->a);
     DestructString(&obj->b);
     DestructString(&obj->c);
}

destruct 函数在每个函数作用域的末尾被调用,就像在 c++ 中一样,只是我手动将它放在那里。因此,现在在 DestructMyObject 函数中,我调用每个 struct string 类型的析构函数,因为对于 struct string 对象,我还将编写一个类似于 struct MyObject 对象的析构函数。

我的问题示例:

int main {
     struct MyObject Object1;
     ConstructMyObject(&Object1);
     ...
     ...
     ...
     TransferOwnershipFunction(Object1.b); /*takes a struct string object as argument*/
     ...
     ...
     ...

     DestructMyObject(&Object1);

    return 0;
}

您看到我已将Object1 的一个成员的所有权转移到另一个函数,但Object1 的所有内容都将被main 函数中的析构函数销毁。

c++ 析构函数如何处理这种情况?我不希望struct string b 的析构函数在main 的末尾被调用,但它会被调用,因为我调用了MyObject 的析构函数。函数TransferOwnershipFunction(...) 现在负责释放字符串对象。

编辑 有人知道 rust 编译器如何解决这个问题吗?所以在 Rust 中,我是否需要 clone 我传递给 TransferOwnershipFunction 的结构字符串对象,或者是否有另一种方法,因为 clone (或 copying 我猜)似乎是一项非常昂贵的操作。

【问题讨论】:

  • 在 C++ 中有一个移动构造函数和复制构造函数。不管你做什么,如果你移动一个对象,原始对象就会知道它被移动并转移了数据的所有权。无论如何都会调用原始对象的析构函数,那里没有什么可以释放的。你应该做类似string_move(struct string *to, struct string *from) { to->data = from->data; from->data = NULL; }
  • 您的示例很难遵循,但这似乎与 C++ 程序员拒绝遵守 rule of 3 时没有什么不同。因此,C++处理这个——程序员处理它。
  • 请提供struct string的代码
  • struct string 将保存一个指向某个堆内存的指针,并在其析构函数中释放该指针。

标签: c++ c destructor ownership


【解决方案1】:

在我看来 main() 应该负责创建和删除 Object1。 TransferOwnershipFunction() 应该与Object1.b 的副本一起使用。在这种情况下:

  1. 您需要创建类似于 复制构造函数赋值运算符 的函数(对于 C++03)。在 C++11 中还添加了 move constructormove assignment operator
  2. 在 C++03 中,复制构造函数赋值运算符如果不声明它们会隐式生成。默认情况下,它们使用每个成员的复制构造函数(除了简单类型,如 int、double ...)按类成员(而不是内存中的字节)复制对象。所以你需要通过调用复制构造函数来模拟通过值传递Object1.b:在TransferOwnershipFunction创建struct string类型的新对象,复制它的内容成员。如果struct string 包含一个原始指针作为成员,并且您在struct string 的构造函数中为此成员调用malloc,在析构函数中调用free,而不是在struct string复制构造函数 中,您需要调用 malloc 而不是从传递的变量中复制所有内容。不要忘记在TransferOwnershipFunction 末尾调用析构函数。
  3. 根据RAII,您需要以与创建对象的顺序(构造函数的顺序)相反的顺序调用析构函数。

【讨论】:

    猜你喜欢
    • 2020-02-16
    • 2021-06-23
    • 2011-04-03
    • 2010-12-16
    • 2016-10-23
    • 2012-04-10
    • 2012-11-14
    • 2016-09-09
    • 1970-01-01
    相关资源
    最近更新 更多