c ++析构函数不会删除对象本身,是什么?
c++ destructor doesn't delete the object itself, what does?
首先,除非我误解了它,否则析构函数会释放对象内部变量占用的内存。在下面的示例中,它将删除 * str 指向的字符串。就这些了。
class StrPtr {
private:
string * str;
public:
StrPtr() : str(new string()) {}
~StrPtr() { delete str; }
void add(char c) { str->push_back(c); }
};
但是,这是我的困惑。如果析构函数不销毁对象本身。这是否意味着:
for 循环后我有 10k StrPtr 对象。
for 循环一结束,10k StrPtr 对象就会被删除,因为它们超出了范围。
每次 someF() 函数完成执行时,对象都会被删除,因为它超出了范围。因为这是创建它的地方。这是我目前的想法。
void someF() {
StrPtr s;
s.add('a');
}
int main() {
for (int i = 0; i < 10000; i++) {
someF();
}
}
请参阅我的问题的选项 3。
没有内存泄漏,内存中永远不会超过一个 StrPtr 对象。
我想您只需要找出 'delete'、'deallocate' 和 'destroy' 之间的区别即可。可以帮助你的是观察
{
A *a = new A;
...
delete a;
}
实际上是这样工作的:
{
A *a = static_cast<A *>(std::malloc(sizeof(A)); // allocate
new (a) A(); // construct [placement new, something like a->A()]
...
a->~A(); // destroy
std::free(a); // deallocate
}
所以,'delete'表示'destroy',然后是'deallocate'。
分别是'create'表示'allocate',然后是'construct'.
在这个方案中,(std::malloc, std::free) 可以用任何其他分配策略代替——看看 https://en.cppreference.com/w/cpp/memory/allocator_traits 。
这同样适用于堆栈上的分配。
{
A a;
B b;
...
}
可能看起来像这样:
{
// push %rbp
// mov %rsp, %rbp
A *pa = <magic> // sub $sizeof(A), %rsp; pa <- %rsp
B *pb = <magic> // sub $sizeof(B), %rsp; pb <- %rsp
A &a = *pa;
B &b = *pb;
...
pb->~B();
pa->~A();
<deallocate everything>
// mov %rbp, %rsp
// pop %rbp
}
如果你想了解堆栈分配的魔力,你最好学习汇编的基础知识——你还将了解调用框架、调用约定和许多其他你通常需要记住的东西推导。
首先,除非我误解了它,否则析构函数会释放对象内部变量占用的内存。在下面的示例中,它将删除 * str 指向的字符串。就这些了。
class StrPtr {
private:
string * str;
public:
StrPtr() : str(new string()) {}
~StrPtr() { delete str; }
void add(char c) { str->push_back(c); }
};
但是,这是我的困惑。如果析构函数不销毁对象本身。这是否意味着:
for 循环后我有 10k StrPtr 对象。
for 循环一结束,10k StrPtr 对象就会被删除,因为它们超出了范围。
每次 someF() 函数完成执行时,对象都会被删除,因为它超出了范围。因为这是创建它的地方。这是我目前的想法。
void someF() {
StrPtr s;
s.add('a');
}
int main() {
for (int i = 0; i < 10000; i++) {
someF();
}
}
请参阅我的问题的选项 3。
没有内存泄漏,内存中永远不会超过一个 StrPtr 对象。
我想您只需要找出 'delete'、'deallocate' 和 'destroy' 之间的区别即可。可以帮助你的是观察
{
A *a = new A;
...
delete a;
}
实际上是这样工作的:
{
A *a = static_cast<A *>(std::malloc(sizeof(A)); // allocate
new (a) A(); // construct [placement new, something like a->A()]
...
a->~A(); // destroy
std::free(a); // deallocate
}
所以,'delete'表示'destroy',然后是'deallocate'。 分别是'create'表示'allocate',然后是'construct'.
在这个方案中,(std::malloc, std::free) 可以用任何其他分配策略代替——看看 https://en.cppreference.com/w/cpp/memory/allocator_traits 。 这同样适用于堆栈上的分配。
{
A a;
B b;
...
}
可能看起来像这样:
{
// push %rbp
// mov %rsp, %rbp
A *pa = <magic> // sub $sizeof(A), %rsp; pa <- %rsp
B *pb = <magic> // sub $sizeof(B), %rsp; pb <- %rsp
A &a = *pa;
B &b = *pb;
...
pb->~B();
pa->~A();
<deallocate everything>
// mov %rbp, %rsp
// pop %rbp
}
如果你想了解堆栈分配的魔力,你最好学习汇编的基础知识——你还将了解调用框架、调用约定和许多其他你通常需要记住的东西推导。