代码之家  ›  专栏  ›  技术社区  ›  cwallenpoole

关于C++中的内存,我需要知道什么?

  •  16
  • cwallenpoole  · 技术社区  · 15 年前

    所以,这里有一个多部分的问题:

    • 关于内存管理,我需要知道的最低要求是什么(或者,我该去哪里找到答案?
    • 我在哪里学习中级和高级知识/教程/等(完成基础知识后)?

    • 我听说在循环中,你需要确保你打电话 delete
    • 内存泄漏的一些经典例子是什么?
    • 关于以下内容,我需要知道什么(我是否真的需要使用它们——如果需要,在哪里?):
      • malloc
      • free
      • calloc
      • realloc

    这是为了在评论一(由Ewan)中提及lmgtfy。如果你开始阅读那里的信息,对初学者来说是没有用的。我认为这是一个伟大的理论,但它对这个问题既不相关也没有用处。

    15 回复  |  直到 15 年前
        1
  •  24
  •   anon anon    15 年前

    你真的真的需要读一本好书——学习C++是坦白的,没有一个是不可能的。我推荐 Accelerated C++

        2
  •  15
  •   Community CDub    7 年前

    基础

    • 数组new与普通new不同,它有自己的delete

     int*  data1 = new int(5);
     delete data1;
    
     int*  data2 = new int[5];
     delete [] data2;
    

    一定知道

    • 例外情况
    • 拉伊
    • 第4条规则。

    throwing exceptions out of a destructor
    Dynamically allocating an array of objects Pattern name for create in constructor, delete in destructor (C++)

    最佳做法

    • 永远不要使用原始指针。
    • 学习不同类型的智能指针以及何时使用

    Smart Pointers: Or who owns you baby?

    高级:

    • 理解例外保证
    • 理解throw子句的用法

    What are the principles guiding your exception handling policy?

    常见的泄漏方式

    // Every new is matched by a delete.
    for(int loop = 0;loop < 10;++loop)
    {
        data = new int(5);
    }
    delete data;
    // The problem is that every 'use of' new is not matched by a delete.
    // Here we allocate 10 integers but only release the last one.
    

    一定知道

    class MyArray
    {
        // Use RAII to manage the dynamic array in an exception safe manor.
        public:
            MyArray(int size)
              :data( new int[size])
            {}
            ~MyArray()
            {
                delete [] data;
            }
        // PROBLEM:
        // Ignored the rule of 4.
        // The compiler will generate a copy constructor and assignment operator.
        // These default compiler generated methods just copy the pointer. This will
        // lead to double deletes on the memory.
    
        private:
            int*   data;
    };
    

    最佳做法

    // Understand what the properties of the smart pointers are:
    //
    std::vector<std::auto_ptr<int> >   data;
    
    // Will not work. You can't put auto_ptr into a standard container.
    // This is because it uses move semantics not copy semantics.
    

    高级:

    // Gurantee that exceptions don't screw up your object:
    //
    class MyArray
    {
       // ... As Above: Plus
       void resize(int newSize)
       {
           delete [] data;
           data = new int[newSize];
           // What happens if this new throws (because there is not enough memory)?
           // You have deleted the old data so the old data so it points at invalid memory.
           // The exception will leave the object in a completely invalid state
       }
    
        3
  •  14
  •   RC.    11 年前

    MyClass *myClass = new MyClass(x); 您需要在代码中有一个位置,用相应的 delete . 这在实践中看起来很容易,但如果没有适当的设计和使用辅助对象(如共享指针),这可能会很快变得混乱,尤其是在维护代码和添加功能时。例如,这里有一个典型的内存泄漏:

    try
    {
        MyClass *myClass = new MyClass(x);
    
        // Do some stuff can throw an exception
    
        delete myClass;
    }
    catch(...)
    {
       // Memory leak on exceptions.  Delete is never called
    }
    

    或者另一个大内存管理系统发现调用了错误的删除类型:

    int* set = new int[100];
    delete set;   // Incorrect - Undefined behavior
    // delete [] set;  is the proper way to delete an array of pointers
    

    Resource Allocation Is Initialization )

    try
    { 
        auto_ptr<MyClass> myClass(new MyClass(x));
        // Now the heap allocated memory associated with myClass
        // will automatically be destroyed when it goes out of scope,
        // but you can use it much like a regular pointer
    
        myClass->memberFunction();
    } 
    catch (...)
    {
    
    }
    

    auto_ptr 可以找到 here . 如果你能使用C++11, shared_ptr

        4
  •  5
  •   Ben S    15 年前

    首先,您应该理解 stack heap .

    理解这些概念后,继续学习语言结构。

        5
  •  5
  •   KitsuneYMG    15 年前

    我该去哪里找到答案?

    我在哪里学习中级和高级知识/教程/等(完成>基本要求是什么?

    阅读 更有效的C++ 有效STL

    更具体地说:指针和引用之间的性能差异是什么?

    我并不清楚,因为引用是指针值的副本,所以我没有预见到任何大的性能问题。

    我听说在循环中,您需要确保在循环重新迭代之前对任何新指针调用delete。这是正确的吗?

    你需要对推荐人做些什么吗?

    内存泄漏的一些经典例子是什么?

    int * foo() {
    ...
    return new int(...);
    }
    
    int main() {
    int i = *foo();
    ...
    //the new int() from foo leaks
    }
    

    首先,你不应该 delete A. malloc 永远都不会 free 使用创建的指针 new . 一般来说,这些函数不应该出现在C++代码中。然而,如果你发现自己在c-land。。。

    malloc:类似于new(在堆上分配内存)
    空闲:类似于删除(在堆上释放内存)
    calloc:类似于new+memset(在堆上分配内存,将其设置为零)
    自由的 我在用旧指针。没有真正的C++等价物。

    谷歌搜索可以找到一些整洁的记忆材料(是这样拼写的吗?) placement new

        6
  •  4
  •   Otávio Décio    15 年前

    你应该调查一下 smart pointers

        7
  •  3
  •   Nikola Smiljanić    15 年前

    对于C/C++新手来说,这本名为“C和C++中内存作为编程概念”的书是一本非常好的读物。

        8
  •  2
  •   Paul Butcher    15 年前

    new delete -有人说永远不要使用 malloc free

    delete[] .

        9
  •  2
  •   stephenbayer    15 年前

    当我用C++语言分配内存时,我首先要在使用它之前先把它重新分配。换句话说,我编写分配,然后分配,然后填充中间。养成一贯的习惯很重要。我认为这是最起码要学的。。。对资源进行适当和有纪律的管理。这不仅仅与内存有关,还应该应用于所有资源,包括数据库引用、文件引用、上下文句柄和其他类似的动物。

    例子:

    char* myusedmemory;
    
    myusedmemory = (char *)malloc(1000);  // allocate memory
    
    free(myusedmemory);  //  immediately deallocate memory
    
    /*  go back and fill in the code between */
    

    关于这一主题的更多知识,有很多很好的参考资料。我发现浏览relisoft.com上的教程对我很有帮助,尽管关于relisoft.com的主要教程是针对Windows的。 Another good reference can be found here.

    至于指针和引用之间的区别,主要区别之一是灵活性。您必须立即定义引用(int iExample;国际及;refExample=iExample;)我认为不会有太大的性能差异。然而,更强大、更灵活的指针将更危险,并且需要上述规则来管理。

    examples of memory leaks are here . 但你可以通过谷歌搜索“C++内存泄漏”找到更多信息

    malloc , free , calloc , realloc ,这些函数与任何其他命令一样,在这些特定情况下,是stdlib中包含的函数。您应该了解它们的功能和使用方法,就像您对其他函数的理解一样,就像常见的printf()一样。

    请注意: Smart pointers

    另外,我想提一下, Code Complete ,这是我读过的关于资源管理的最好的书。我从头到尾读了很多遍。

        10
  •  2
  •   DrPizza    15 年前

    在其他语言中,您已经必须使用诸如“finally”(在Java中)或“using”(在C#中)之类的机制来跟踪数据库连接、窗口句柄、套接字等。在C++中,只需将内存添加到列表中即可。这在概念上并没有什么不同。

        11
  •  1
  •   Thomas Matthews    15 年前

    new ).

    另外,不要在大型物体周围走动。向对象传递指针,最好是智能指针。复制大型对象会占用大量处理器时间。

    设置并记录有关对象分配和所有权的规则。被调用方还是调用方拥有该对象?

    不要返回对本地对象的引用,也不要返回指向本地对象的指针。

        12
  •  1
  •   Tristram Gräbener    15 年前

    新的C++用户倾向于像java那样在任何地方都“新”。在很多情况下,这是一个坏习惯,在某些情况下你无法避免(但从我的项目经验来看,这很可能永远不会)。

        13
  •  1
  •   static_rtti    15 年前

    • 最好的办法是使用标准容器,让用户进行内存管理。
    • 当这是不可能的时候,使用智能指针进行引用计数,或者在最后的手段中使用更智能的垃圾收集。

    当然,出于性能原因,您可能希望在性能关键型中偶尔有一个new和delete对,但这应该是例外,而不是规则。

        14
  •  0
  •   MrSlippers    15 年前

    new delete 是内存管理的两个最重要的关键字。最简单的说,你只需要记得打电话 删除 新的 新的 删除 在每一个上面 "被炸物体"。只要将每个指针的副本保存在以后可以删除的地方,就不需要从循环中执行此操作。

    malloc free , calloc ,及 realloc 新的 / 删除 曾经觉得自己受到了限制。

        15
  •  0
  •   Scottie T    15 年前

    在我学习C++的时候,我发现使用内存分析工具 Valgrind 在帮助查找内存泄漏时是必不可少的。当您从Valgrind运行程序(使用调试符号编译)时,它将标识分配内存但以后永远不会释放内存的行。

    我使用以下命令行参数:

     valgrind --leak-check=yes --num-callers=8 ./myExecutable
    

    请注意,您的程序将比单独运行时运行得慢得多,但这通常是值得的。