Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++;,是否有处理内存分配/删除的一般准则?_C++_Memory_Memory Management_Pointers - Fatal编程技术网

C++ 在C++;,是否有处理内存分配/删除的一般准则?

C++ 在C++;,是否有处理内存分配/删除的一般准则?,c++,memory,memory-management,pointers,C++,Memory,Memory Management,Pointers,也许我想要的只是一个我还没有找到的网站的链接。但是,从java背景来看,C++中处理内存分配和删除的一般准则是什么?我觉得我可能会在我的应用程序中添加各种各样的内存泄漏。我意识到智能指针有几种变体,你也可以提到它们,但是我想把重点放在标准C++指针上。 通常,我们使用新< /Cord>分配内存,并且删除< /C> >释放它。(主要是因为new调用适当的构造函数,以及delete适当的析构函数) 但是这里的大多数人都会建议您不要将原始指针用于教育目的以外的目的(除非智能指针的开销很大,比如在嵌入式

也许我想要的只是一个我还没有找到的网站的链接。但是,从java背景来看,C++中处理内存分配和删除的一般准则是什么?我觉得我可能会在我的应用程序中添加各种各样的内存泄漏。我意识到智能指针有几种变体,你也可以提到它们,但是我想把重点放在标准C++指针上。

通常,我们使用<代码>新< /Cord>分配内存,并且<代码>删除< /C> >释放它。(主要是因为

new
调用适当的构造函数,以及
delete
适当的析构函数)

但是这里的大多数人都会建议您不要将原始指针用于教育目的以外的目的(除非智能指针的开销很大,比如在嵌入式编程中)

了解事物的工作原理很重要,但在大多数情况下,您可以利用设计良好的智能指针类使事情变得更简单(通常更安全)


智能指针的存在有一个原因:帮助程序员完成伟大的程序,而不必太在意分配/解除分配。

使用带有极端偏执的指针。对于在类中声明的每个成员变量,记录它是否拥有所指向内存的内存生存期。如果有,则负责分配和释放内存。如果它确实拥有它指向的内存,请清楚地记录它! 还要记住,在构造函数中分配,在析构函数中取消分配。这是一条伟大的规则,如果你忽视它,后果自负。 除了在使用指针外,还可以将指针设为空。初始化它们时,以及释放它们后,将它们设置为NULL。 在取消引用指针之前,将大量断言放在任何地方检查指针的完整性。 当情况不好时,派真正的警卫来处理

最后也是最重要的一点:

解雇公司中任何滥用这些政策的笨蛋!!!他们实际上是在给你的产品注入无法形容的伤害,并在未来的道路上造成了大量的bug和头痛

编辑:
我通常的政策是

  • 在使用非常复杂的地方使用智能指针
  • 所有原始指针都属于负责删除它的特定对象
  • 构造函数总是要么分配指针,要么将其初始化为null(如果以后要设置)
  • 析构函数总是删除任何包含的指针
  • 这些规则确保在删除指针所属对象时删除指针,从而消除最常见的内存泄漏情况
  • 永远不要将内部指针传递到另一个对象,始终传递容器对象,并让被调用的函数调用容器对象的成员函数作用于“指针”
  • 禁用容器对象的复制。在极少数情况下,实现复制以复制指向的对象。但是,在不复制包含的对象的情况下,绝不允许复制拥有对象
  • 前两条规则确保不能有指向已删除内存的指针副本
  • 不要尝试实现引用计数。如果需要引用计数指针,请使用智能指针类并包含该类

<>我发现这些规则通常确保你可以安全有效地使用原始指针,如果你想打破这些规则,那么就使用智能指针。

< P>我也是来自java,而且花了很长时间才知道C++中的好设计是什么样子。一开始,很难想象删除东西是谁的责任。答案是将这些责任推给对象,让对象拥有/管理其他对象或资源,让他们担心删除/发布或复制。C++通过构造函数、析构函数等使之变得简单。关键字是“RAII”(资源获取是初始化)。
通常,我会将“x拥有y”关系组织为一个树的根都位于堆栈上的森林(自动内存)。通过使用标准容器和避免指针作为数据成员,我将代码中的new/delete调用数量减少到了最低限度(几乎没有)。这是最简单的处理方法。有时,您可能会觉得需要使用共享所有权智能指针,但根据我的经验,人们往往会过度使用这些指针。当然,它们在某些情况下是有用的。

如果您确实需要处理原始指针,那么我建议尽可能使用智能指针包装它们。如果要将它们存储在STL容器中,则需要使用
tr1::shared_ptr
而不是
auto_ptr

在你学习的过程中,我建议你尽可能避开指针,以避免头痛。例如,如果您想要一个
int
s数组,可以使用
向量,而不是自己分配和释放内存。如果你想实例化一个类,可以在自动内存中进行

MyClass myObject;
而不是

MyClass *myObject = new MyClass();
// ...
delete myObject;

将每个
new
(或
new[]
)与
delete
(或
delete[]
)配对


他是你的朋友。开发在构造函数中获取资源并在析构函数中释放它们的类。

您想过使用垃圾收集器吗。目前Mono项目正在使用它,尽管我知道它正在被一个更具攻击性的版本所取代。它可能会有所帮助,因为在C/C++中开发时,它将提供与在Java上开发时类似的体验

我使用以下策略:

  • 永远不要使用拥有对象的原始指针

    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
    
  • 对于共享所有权或容器,请使用
    boost::shared_ptr
    std::tr1::shared_ptr

    std::auto_ptr<Foo> f(new Foo()); // Good
    
    std::vector<boost::shared_ptr<Foo> > foos;
    
    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
    
    因此,很明显谁给了谁一个指针

  • 原始指针仅允许作为
    void bar1(Foo *f) { do something with f if f!=NULL}