我要求的所有内容都可能是指向我尚未找到的网站的链接。但是来自Java背景,在C ++中处理内存分配和删除的一般原则是什么?我觉得我可能会在我的应用程序中添加各种内存泄漏。我意识到有几种智能指针的变种,你也可以提到我,但我想关注标准的C ++指针。
答案 0 :(得分:17)
我通常的政策就是这个
我发现这些规则通常可以确保您可以安全有效地使用原始指针,如果您想破坏这些规则,那么请使用智能指针。
答案 1 :(得分:5)
通常,我们使用new
来分配内存,使用delete
来释放内存。 (主要是因为new
调用了适当的构造函数,而delete
调用了适当的析构函数。)
但是大多数人会建议你不要使用原始指针而不是用于教育目的(除非智能指针的开销很大,比如嵌入式编程)。
了解工作是很重要的,但在大多数情况下,您可以利用设计良好的智能指针类来使您更轻松(并且通常更安全)。
智能指针存在的原因是:帮助程序员完成优秀的程序,而不必关心太多处理分配/解除分配。
答案 2 :(得分:5)
使用极端偏执的指针。对于在类中声明的每个成员变量,记录它是否拥有它指向的内存的内存生存期。如果是,那么它负责分配和释放内存。如果它确实拥有它指向的内存,请将其清楚地记录下来! 还记得,在构造函数中分配并在析构函数中释放。这是一个很好的规则,你忽略了你的危险。 除了你使用它们之外,你的指针也是空的。初始化时将它们清空,然后释放它们。 在解除引用它们之前,将大量断言放在检查指针完整性的地方。 放入真正的警卫来处理他们不好的情况。
最后也是最重要的:
点燃贵公司任何滥用这些政策的bozo !!!它们确实会给您的产品注入无法估量的伤害,并在路上造成大量的虫子和头痛。
答案 3 :(得分:4)
我也来自Java,花了一些时间来了解C ++中的优秀设计。起初,很难想象删除事物的责任是谁。答案是将这些职责推迟到对象,让对象拥有/管理其他对象或资源,让他们担心删除/释放或复制。 C ++使构造函数,析构函数等变得容易。它们的关键字是“RAII”(资源获取是初始化)。
通常,我设法将“x拥有y” - 关系组织为一个森林,其中树的根存在于堆栈(自动存储器)中。通过使用标准容器并避免指针作为数据成员,我将代码中的新/删除调用的数量减少到最少(几乎没有)。这是最简单的方法。有时,您可能觉得需要使用共享所有权智能指针,但根据我的经验,人们倾向于过度使用这些指针。但它们在某些情况下当然有用。
答案 4 :(得分:4)
将每个new
(或new[]
)与delete
(或delete[]
)配对。
RAII是你的朋友。开发在构造函数中获取资源的类,并在析构函数中释放它们。
答案 5 :(得分:1)
如果你确实需要处理原始指针,那么我建议如果可能的话用智能指针包装它们。如果您要将它们存储在STL容器中,则需要使用tr1::shared_ptr
而不是auto_ptr
。
在你学习的过程中,我建议你尽可能避免指点,以避免头痛。例如,如果你想要一个int
的数组,你可以使用vector
而不是自己分配和释放内存。如果要实例化一个类,请在自动存储器中进行,即
MyClass myObject;
而不是
MyClass *myObject = new MyClass();
// ...
delete myObject;
答案 6 :(得分:1)
我使用以下政策:
永远不要使用拥有对象的原始指针。
Foo *f=new Foo(); // Bad!
即使在课程中:
class Bar {
Bar(Bar const &); // non copyable
void operator=(Bar const &);
public:
Bar() {
f1_=new Foo();
f2_=new Foo(); // this throws then f1_ never destroyed!
}
~Bar() { delete f1_; delete f2_ ;}
Foo *f1_,*f2_;
};
// Bad code
正确:
class Bar {
Bar(Bar const &); // non copyable
void operator=(Bar const &);
public:
Bar() {
f1_.reset(new Foo())
f2_.reset(new Foo());
}
std::auto_ptr<Foo> f1_,f2_;
};
// Good code
对于没有共享所有权的对象,请使用auto_ptr
std::auto_ptr<Foo> f(new Foo()); // Good
对于共享所有权或容器,请使用boost::shared_ptr
或std::tr1::shared_ptr
std::vector<boost::shared_ptr<Foo> > foos;
当我需要将对象的所有权转移给其他对象时,请使用auto_ptr
void assign_foo(std::auto_ptr<Foo> f)
{
/// I own foo
}
std::auto_ptr<Foo> transfer_foo(std::auto_ptr<Foo> f) { ... }
// Now foo is owned by caller
所以很清楚谁给谁一个指针。
原始指针仅允许作为可以为null的引用 从不拥有对象
void bar1(Foo *f) { do something with f if f!=NULL}
答案 7 :(得分:0)
您是否考虑过使用垃圾收集器?这个Garbage Collector目前被Mono项目使用,虽然我知道它会被更积极的版本所取代。它可能会有所帮助,因为它将在使用C / C ++进行开发时提供类似的体验,就像您在Java上开发一样。
答案 8 :(得分:0)
正如其他人所说,你需要阅读RAII。我发现this在我学习C ++时非常有用,它已经很老了,但却提供了基本的想法。