英文:
Is this the correct way to deallocate a new object?
问题
以下是代码的翻译部分:
#include <iostream>
class Dude
{
public:
int age;
Dude(int age)
{
this->age = age;
}
};
int main(int argc, char* argv[])
{
Dude *dude1 = new Dude(21);
std::cout << dude1->age << '\n';
delete dude1;
return 0;
}
这段代码的主要目的是创建一个名为"Dude"的类,然后在main
函数中创建一个"Dude"类的实例,使用new
运算符分配内存,并在程序结束时使用delete
运算符释放内存。以下是关于你提到的其他问题的回答:
-
是的,使用
delete dude1;
是正确的方法来释放dude1
的内存并销毁dude1
对象。 -
如果保留默认析构函数,它将不执行任何额外的内存清理或资源释放,因为在默认析构函数中没有显式的清理代码。默认析构函数的存在是为了确保对象被销毁时,与其相关的内存被释放,但在这个特定的情况下,
Dude
类没有需要额外处理的资源。 -
dude1->~Dude();
这行代码调用了Dude
类的析构函数,手动销毁了dude1
对象。通常情况下,不需要手动调用析构函数,因为在对象离开其作用域或通过delete
运算符释放内存时,析构函数会自动被调用。手动调用析构函数通常不是必要的,只有在特殊情况下才会使用。
英文:
#include <iostream>
class Dude
{
public:
int age;
Dude(int age)
{
this->age = age;
}
};
int main(int argc, char* argv[])
{
Dude *dude1 = new Dude(21);
std::cout << dude1->age << '\n';
delete dude1;
return 0;
}
Is this the correct way to deallocate the memory of dude1
and to destroy the object dude1
?
What memory deallocation and cleanup is the destructor doing if left as the default destructor?
dude1->~Dude();
What does this piece of code do?
答案1
得分: 5
This is the translated text:
> Is this the correct way to deallocate the memory of dude1
and to destroy the object dude1
?
这是否是释放dude1
的内存并销毁对象dude1
的正确方式?
Yes, it is technically correct.
是的,从技术上讲是正确的。
But, it is not the best option. A better option would be to create the Dude
object in automatic storage, and not worry about its deallocation/cleanup at all, let the compiler worry about that for you, eg:
但这不是最佳选项。更好的选择是在自动存储中创建Dude
对象,完全不用担心它的释放/清理工作,让编译器来处理,例如:
int main(int argc, char* argv[])
{
Dude dude1(21);
std::cout << dude1.age << '\n';
return 0;
}
如果必须动态创建对象,至少要使用std::unique_ptr
之类的智能指针,这样就不需要手动delete
对象,例如:
#include <memory>
int main(int argc, char* argv[])
{
auto dude1 = std::make_unique<Dude>(21);
// 在C++14之前,可以使用以下方式代替:
// std::unique_ptr<Dude> dude1(new Dude(21));
std::cout << dude1->age << '\n';
return 0;
}
> What memory deallocation and cleanup is the destructor doing if left as the default destructor?
如果将析构函数保留为默认析构函数,它会执行什么内存释放和清理操作?
In this example, nothing at all.
在这个例子中,根本什么都不做。
In general, when you deal with objects, there is a clear separation of responsibilities between allocation/deallocation and creation/destruction. Memory for the object is reserved first, then the object is created within that memory. Later, the object is destroyed first, and then its memory is released.
一般而言,当你处理对象时,分配/释放 和 创建/销毁 之间有明确的责任分工。首先保留对象的内存,然后在该内存中创建对象。随后,首先销毁对象,然后释放其内存。
When an object has automatic storage duration, its memory is reserved within the calling scope (ie, a local variable in a function/block, a data member of a class, etc), and it is created within that scope's memory. When that scope ends (ie, the function/block ends, the containing object is destroyed, etc), the scoped object is automatically destroyed and its memory is released.
当一个对象具有自动存储期时,其内存在调用作用域内被保留(例如,在函数/块中的局部变量、类的数据成员等),并在该作用域的内存中创建。当该作用域结束时(即函数/块结束、包含的对象被销毁等),作用域内的对象将被自动销毁,其内存将被释放。
Thus, in your example, the default destructor of Dude
does nothing, since there is nothing for it to destroy.
因此,在您的示例中,Dude
的默认析构函数不执行任何操作,因为没有需要销毁的内容。
Dude
has a single int
data member, which is created with automatic storage duration within Dude
. When a Dude
object is created, space for the int
is included in the memory allocation for the Dude
object, but the int
is not valid for use until the Dude
object is constructed within that memory. Later, when the Dude
object is destroyed, the int
becomes invalid for use when the Dude
object's destructor is called, and then the memory for the int
disappears when the memory for the Dude
object is deallocated.
Dude
有一个int
数据成员,它在Dude
内具有自动存储期。当创建一个Dude
对象时,为Dude
对象的内存分配中包括了int
的空间,但在Dude
对象在该内存中构造之前,int
不可用。随后,当销毁Dude
对象时,Dude
对象的析构函数被调用时,int
变得不可用,并且当Dude
对象的内存被释放时,int
的内存也会消失。
In my first example above, the Dude
object has automatic storage duration. Its scope is main()
, so the compiler reserves memory inside the stack frame of main()
to hold the Dude
object, and then creates the Dude
object (ie, calls its constructor) within that memory. When main()
exits, the Dude
object goes out of scope and is destroyed (ie, its destructor is called), and its memory is released when the stack frame is cleaned up.
在我上面的第一个示例中,Dude
对象具有自动存储期。其作用域是main()
,因此编译器在main()
的堆栈帧内部保留内存以容纳Dude
对象,然后在该内存中创建Dude
对象(即调用其构造函数)。当main()
退出时,Dude
对象超出作用域并被销毁(即调用其析构函数),当堆栈帧被清理时,它的内存被释放。
In my second example above, the Dude
object has dynamic storage duration. Its scope is dynamic memory. new
allocates dynamic memory to hold the Dude
object, and then creates the Dude
object (ie, calls its constructor) within that memory. Later, delete
destroys the Dude
object (ie, calls its destructor) and deallocates the dynamic memory that new
had allocated.
在我上面的第二个示例中,Dude
对象具有动态存储期。其作用域是动态内存
英文:
> Is this the correct way to deallocate the memory of dude1
and to destroy the object dude1
?
Yes, it is technically correct.
But, it is not the best option. A better option would be to create the Dude
object in automatic storage, and not worry about its deallocation/cleanup at all, let the compiler worry about that for you, eg:
int main(int argc, char* argv[])
{
Dude dude1(21);
std::cout << dude1.age << '\n';
return 0;
}
If you must create the object dynamically, at least use a smart pointer like std::unique_ptr
so you don't need to delete
the object manually, eg:
#include <memory>
int main(int argc, char* argv[])
{
auto dude1 = std::make_unique<Dude>(21);
// prior to C++14, use this instead:
// std::unique_ptr<Dude> dude1(new Dude(21));
std::cout << dude1->age << '\n';
return 0;
}
> What memory deallocation and cleanup is the destructor doing if left as the default destructor?
In this example, nothing at all.
In general, when you deal with objects, there is a clear separation of responsibilities between allocation/deallocation and creation/destruction. Memory for the object is reserved first, then the object is created within that memory. Later, the object is destroyed first, and then its memory is released.
When an object has automatic storage duration, its memory is reserved within the calling scope (ie, a local variable in a function/block, a data member of a class, etc), and it is created within that scope's memory. When that scope ends (ie, the function/block ends, the containing object is destroyed, etc), the scoped object is automatically destroyed and its memory is released.
Thus, in your example, the default destructor of Dude
does nothing, since there is nothing for it to destroy.
Dude
has a single int
data member, which is created with automatic storage duration within Dude
. When a Dude
object is created, space for the int
is included in the memory allocation for the Dude
object, but the int
is not valid for use until the Dude
object is constructed within that memory. Later, when the Dude
object is destroyed, the int
becomes invalid for use when the Dude
object's destructor is called, and then the memory for the int
disappears when the memory for the Dude
object is deallocated.
In my first example above, the Dude
object has automatic storage duration. Its scope is main()
, so the compiler reserves memory inside the stack frame of main()
to hold the Dude
object, and then creates the Dude
object (ie, calls its constructor) within that memory. When main()
exits, the Dude
object goes out of scope and is destroyed (ie, its destructor is called), and its memory is released when the stack frame is cleaned up.
In my second example above, the Dude
object has dynamic storage duration. Its scope is dynamic memory. new
allocates dynamic memory to hold the Dude
object, and then creates the Dude
object (ie, calls its constructor) within that memory. Later, delete
destroys the Dude
object (ie, calls its destructor) and deallocates the dynamic memory that new
had allocated.
Note that the int
inside of Dude
always has automatic storage duration. Its scope is Dude
, so it gets allocated wherever a Dude
object is allocated, and is deallocated whenever the Dude
object is deallocated. Whether that be in automatic memory (ie, the stack) or in dynamic memory (ie, the heap).
> dude1->~Dude();
>
> What does this piece of code do?
It explicitly calls the object's destructor, like any other method call. However, DO NOT DO THIS, except for objects that have been constructed with placement-new
, eg:
int main(int argc, char* argv[])
{
// FYI, this is not the correct way to ensure the allocated memory
// is satisfactory for creating an object in it, this is simplified
// just for demonstration purposes!
char *buffer = new char[sizeof(Dude)];
Dude *dude1 = new (buffer) Dude(21);
std::cout << dude1->age << '\n';
dude1->~Dude();
delete[] buffer;
return 0;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论