C++ 析构函数和所有权
C++ Destructors and Ownership
我尝试在我的 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 我猜)似乎是一个非常昂贵的操作。
从我的角度来看,main() 应该负责创建和删除 Object1。 TransferOwnershipFunction() 应该与 Object1.b
的副本一起使用。在这种情况下:
- 您需要创建类似于复制构造函数和赋值运算符(对于C++03)的函数。 移动构造函数和移动赋值运算符也在C++11中添加。
- 在 C++03 中,复制构造函数 和 赋值运算符 如果您不声明它们,则会隐式生成它们。默认情况下,它们使用每个成员的 复制构造函数 按 class 的成员(而不是内存中的字节)复制对象(除了简单类型,如 int、double...)。因此,您需要通过调用 复制构造函数 来模仿按值传递
Object1.b
:在 TransferOwnershipFunction
中创建类型为 struct string
、[=24 的新对象=]复制 会员的内容。如果 struct string
包含一个原始指针作为成员,并且您在 struct string
的构造函数中为该成员调用 malloc
,在析构函数中调用 free
而不是在 复制构造函数中 的 struct string
你需要调用 malloc
而不是从传递的变量中复制所有内容。不要忘记在 TransferOwnershipFunction
. 末尾调用析构函数
- 根据RAII,您需要以与创建对象的顺序(构造函数的顺序)相反的顺序调用析构函数。
我尝试在我的 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 我猜)似乎是一个非常昂贵的操作。
从我的角度来看,main() 应该负责创建和删除 Object1。 TransferOwnershipFunction() 应该与 Object1.b
的副本一起使用。在这种情况下:
- 您需要创建类似于复制构造函数和赋值运算符(对于C++03)的函数。 移动构造函数和移动赋值运算符也在C++11中添加。
- 在 C++03 中,复制构造函数 和 赋值运算符 如果您不声明它们,则会隐式生成它们。默认情况下,它们使用每个成员的 复制构造函数 按 class 的成员(而不是内存中的字节)复制对象(除了简单类型,如 int、double...)。因此,您需要通过调用 复制构造函数 来模仿按值传递
Object1.b
:在TransferOwnershipFunction
中创建类型为struct string
、[=24 的新对象=]复制 会员的内容。如果struct string
包含一个原始指针作为成员,并且您在struct string
的构造函数中为该成员调用malloc
,在析构函数中调用free
而不是在 复制构造函数中 的struct string
你需要调用malloc
而不是从传递的变量中复制所有内容。不要忘记在TransferOwnershipFunction
. 末尾调用析构函数
- 根据RAII,您需要以与创建对象的顺序(构造函数的顺序)相反的顺序调用析构函数。