为什么使用“新"会导致内存泄漏?
我先学了 C#,现在我开始学习 C++.据我了解,C++ 中的运算符 new
与 C# 中的运算符不同.
I learned C# first, and now I'm starting with C++. As I understand, operator new
in C++ is not similar to the one in C#.
你能解释一下这个示例代码中内存泄漏的原因吗?
Can you explain the reason of the memory leak in this sample code?
class A { ... };
struct B { ... };
A *object1 = new A();
B object2 = *(new B());
推荐答案
发生了什么
当您编写 T t;
时,您正在创建具有 自动存储持续时间 的 T
类型的对象.超出范围时会自动清理.
When you write T t;
you're creating an object of type T
with automatic storage duration. It will get cleaned up automatically when it goes out of scope.
当您编写 new T()
时,您正在创建一个具有 动态存储持续时间 的 T
类型的对象.它不会自动清理.
When you write new T()
you're creating an object of type T
with dynamic storage duration. It won't get cleaned up automatically.
您需要将指向它的指针传递给 delete
以便清理它:
You need to pass a pointer to it to delete
in order to clean it up:
但是,您的第二个示例更糟糕:您正在取消引用指针,并制作对象的副本.这样一来,您就会丢失指向使用 new
创建的对象的指针,因此即使您愿意,也永远无法删除它!
However, your second example is worse: you're dereferencing the pointer, and making a copy of the object. This way you lose the pointer to the object created with new
, so you can never delete it even if you wanted!
你应该做什么
您应该更喜欢自动存储期限.需要一个新对象,只需写:
You should prefer automatic storage duration. Need a new object, just write:
A a; // a new object of type A
B b; // a new object of type B
如果您确实需要动态存储持续时间,请将指向分配对象的指针存储在自动存储持续时间对象中,该对象会自动删除它.
If you do need dynamic storage duration, store the pointer to the allocated object in an automatic storage duration object that deletes it automatically.
template <typename T>
class automatic_pointer {
public:
automatic_pointer(T* pointer) : pointer(pointer) {}
// destructor: gets called upon cleanup
// in this case, we want to use delete
~automatic_pointer() { delete pointer; }
// emulate pointers!
// with this we can write *p
T& operator*() const { return *pointer; }
// and with this we can write p->f()
T* operator->() const { return pointer; }
private:
T* pointer;
// for this example, I'll just forbid copies
// a smarter class could deal with this some other way
automatic_pointer(automatic_pointer const&);
automatic_pointer& operator=(automatic_pointer const&);
};
automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically
这是一个常见的习惯用法,名称不是很具描述性的 RAII(资源获取即初始化).当您获得需要清理的资源时,将其粘贴在自动存储期限的对象中,因此您无需担心清理它.这适用于任何资源,无论是内存、打开的文件、网络连接还是您喜欢的任何资源.
This is a common idiom that goes by the not-very-descriptive name RAII (Resource Acquisition Is Initialization). When you acquire a resource that needs cleanup, you stick it in an object of automatic storage duration so you don't need to worry about cleaning it up. This applies to any resource, be it memory, open files, network connections, or whatever you fancy.
automatic_pointer
这个东西已经以各种形式存在,我只是提供它来举例.标准库中存在一个非常相似的类,称为 std::unique_ptr
.
This automatic_pointer
thing already exists in various forms, I've just provided it to give an example. A very similar class exists in the standard library called std::unique_ptr
.
还有一个旧的(C++11 之前的)名为 auto_ptr
但现在已弃用,因为它有一种奇怪的复制行为.
There's also an old one (pre-C++11) named auto_ptr
but it's now deprecated because it has a strange copying behaviour.
还有一些更聪明的例子,比如 std::shared_ptr
,它允许多个指针指向同一个对象,并且只有在最后一个指针被销毁时才清理它.
And then there are some even smarter examples, like std::shared_ptr
, that allows multiple pointers to the same object and only cleans it up when the last pointer is destroyed.
相关文章