我已经开始使用C ++,并且需要一些有关C ++中的内存管理的说明。我遇到过智能指针,但是我希望了解一些基本概念。
这是一个示例结构
struct A
{
private:
int a;
void* b;
public:
A(int i, void* m) { a=i; b=m; }
};
main()
{
A * a1 = new A(10, 0);
//
//Some Code
if(on some condition) {
delete a1;
a1=nullptr;
}
}
当我删除a1时,m是否也会被自动删除?还是应该在删除a1之前明确删除m,如下所示?
delete a1->b;
a1->b = nullptr;
delete a1;
a1=nullptr;
答案 0 :(得分:4)
当我删除a1时,m也会自动删除
不,不会(您的代码可能有内存泄漏)。您需要一个明确的destructor删除它。
顺便说一句,使用void*b;
指针字段的味道不好。如果您知道,则应该使用一些更明确的类型(例如double*b;
或SomeClass* b;
)。这使您的代码更具可读性,并在编译时提供了更多有用的类型检查机会。
// inside struct A
~A() { delete b; };
了解rule of five。
请注意,在C ++中,struct
-s是very similar到class
-es。
避免使用memory leaks。诸如valgrind之类的工具可能会有所帮助。并且系统地使用smart pointers和标准容器应该有助于避免它们。如果您的字段b
was声明了std::shared_ptr<std::string> b;
,则默认析构函数将适当地释放它。也许您希望它是某个std::vector<std::string>
(同样,默认析构函数会适当地释放内存)。
一个好的编码提示是,在可能的情况下,避免声明raw pointers(最好使用智能指针和容器)。当必须声明一个时,您需要对其delete
进行适当的编码。
答案 1 :(得分:2)
欢迎使用C ++,这是一种功能非常强大的语言,要求您对细节负责,以实现允许这种功能的灵活性。如果愿意,可以使其非常复杂,但是对于大多数结构而言,它们也是一种简便的方法。
首先,您不需要释放内存,如果程序退出,它将清除它。但是,由于您不调用delete,因此不会调用Dtor,这可能导致特定代码无法执行。 因此,通常,清理分配的内存是个好习惯。
new A(10, 0)
将在堆上分配内存。如果您不希望这样做,也可以在堆栈上创建它。会导致自动清除:A a{10, nullptr};
一旦您决定需要堆分配的内存,则应默认为std::unique_ptr
。它将代码更改为:auto a = std::make_unique<A>(10, nullptr);
这样,所有权就在unique_ptr中,可以在(std :: move)中移动。如果您不想转让所有权,则可以取消引用它或调用方法get
。
应用这两种做法(包括针对成员的做法)将防止大量内存泄漏,并减少您需要考虑的时间。
void *是邪恶的,除非有必要,否则不要使用它(并且只有在与C接口时才必须使用)。有很多避免它的方法。最好的是引入一个界面。
class I {
public:
virtual ~I() = default;
};
class M : public I
{
// ...
};
class A
{
// ...
std::unique_ptr<I> m;
// ...
};
有时候,您在Dtor中需要一些特殊的东西,只有在这种情况下,您才应该明确实现Dtor。鉴于您的问题,我将假设您是一个初学者,因此暂时不需要了解更多详细信息。