【问题标题】:How to dynamically allocate arrays in C++如何在 C++ 中动态分配数组
【发布时间】:2016-02-21 04:44:49
【问题描述】:

我知道如何在C中为数组动态分配空间。可以这样做:

L = (int*)malloc(mid*sizeof(int)); 

内存可以通过以下方式释放:

free(L);

如何在 C++ 中实现等效?

具体来说,如何使用newdelete[] 关键字?尤其是在创建/销毁链表节点,或创建和销毁其大小由编译时变量给出的数组的上下文中?

【问题讨论】:

标签: c++ arrays new-operator


【解决方案1】:
int* L = new int[mid]; 
delete[] L;

对于数组(这是你想要的)或

int* L = new int;   
delete L;

对于单个元素。

但是使用vector,或者使用smartpointers更简单,那就不用担心内存管理了。

std::vector<int> L(mid);

L.data() 让您可以访问int[] 数组缓冲区,您可以稍后通过L.resize() 向量。

auto L = std::make_unique<int[]>(mid);

L.get() 给你一个指向int[] 数组的指针。

【讨论】:

    【解决方案2】:

    以下信息将很有用: 来源:https://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/

    初始化动态分配的数组

    如果要将动态分配的数组初始化为0,语法很简单:

    int *array = new int[length]();
    

    在 C++11 之前,没有简单的方法将动态数组初始化为非零值(初始化列表仅适用于固定数组)。这意味着您必须循环遍历数组并显式分配元素值。

    int *array = new int[5];
    array[0] = 9;
    array[1] = 7;
    array[2] = 5;
    array[3] = 3;
    array[4] = 1;
    

    超级烦人!

    不过,从 C++11 开始,现在可以使用初始化列表来初始化动态数组!

    int fixedArray[5] = { 9, 7, 5, 3, 1 }; // initialize a fixed array in C++03
    int *array = new int[5] { 9, 7, 5, 3, 1 }; // initialize a dynamic array in C++11
    

    请注意,此语法在数组长度和初始化列表之间没有 operator=。

    为了一致性,在 C++11 中,固定数组也可以使用统一初始化进行初始化:

    int fixedArray[5] { 9, 7, 5, 3, 1 }; // initialize a fixed array in C++11
    char fixedArray[14] { "Hello, world!" }; // initialize a fixed array in C++11
    

    需要注意的是,在 C++11 中,您不能从 C 风格的字符串初始化动态分配的 char 数组:

    char *array = new char[14] { "Hello, world!" }; // doesn't work in C++11
    

    如果您需要这样做,请改为动态分配 std::string(或分配您的 char 数组,然后将字符串 strcpy 放入)。

    还要注意动态数组必须用明确的长度声明:

    int fixedArray[] {1, 2, 3}; // okay: implicit array size for fixed arrays
    
    int *dynamicArray1 = new int[] {1, 2, 3}; // not okay: implicit size for dynamic arrays
    
    int *dynamicArray2 = new int[3] {1, 2, 3}; // okay: explicit size for dynamic arrays
    

    【讨论】:

      【解决方案3】:

      您使用new 运算符分配内存并使用delete 运算符释放指针。注意不能删除普通变量,只有指针和数组完成任务后才能删除。

      int * foo;
      foo = new int [5];
      delete[] foo;
      

      一个完整的程序

      #include <iostream>
      #include <new>
      using namespace std;
      
      int main ()
      {
        int i,n;
        int * p;
        cout << "How many numbers would you like to type? ";
        cin >> i;
        p= new (nothrow) int[i];
        if (p == nullptr)
          cout << "Error: memory could not be allocated";
        else
        {
          for (n=0; n<i; n++)
          {
            cout << "Enter number: ";
            cin >> p[n];
          }
          cout << "You have entered: ";
          for (n=0; n<i; n++)
            cout << p[n] << ", ";
          delete[] p;
        }
        return 0;
      }
      

      结果

      How many numbers would you like to type? 5
      Enter number : 75
      Enter number : 436
      Enter number : 1067
      Enter number : 8
      Enter number : 32
      You have entered: 75, 436, 1067, 8, 32,
      

      【讨论】:

        【解决方案4】:

        在 C++ 中,我们有分配和取消分配动态内存的方法。变量可以通过使用new 运算符 as 来动态分配,

                             type_name *variable_name = new type_name;
        

        数组只不过是连续内存位置的集合,因此,我们可以在 C++ 中动态分配数组,

                             type_name *array_name = new type_name[SIZE];
        

        您可以使用delete 来释放动态分配的空间,如下所示, 对于变量,

                             delete variable_name;
        

        对于数组,

                             delete[] array_name;
        

        【讨论】:

          【解决方案5】:

          在动态内存中使用原始指针时需要非常小心,但这里有一个简单的示例。

          int main() {
              // Normal Pointer To Type
              int* pX = nullptr;
              pX = new int;
              *pX = 3;
          
              std::cout << *pX << std::endl;
          
              // Clean Up Memory
              delete pX;
              pX = nullptr;
          
              // Pointer To Array
              int* pXA = nullptr;
              pXA = new int[10]; // 40 Bytes on 32bit - Not Initialized All Values Have Garbage
              pXA = new int[10](0); // 40 Bytes on 32bit - All Values Initialized To 0.
          
              // Clean Up Memory To An Array Of Pointers.
              delete [] pXA;
              pXA = nullptr;
          
              return 0;     
          
          } // main
          

          为了避免内存泄漏;悬空指针,提前删除内存等。尝试使用智能指针。它们有两种类型:共享的和独特的。

          SomeClass.h

          #ifndef SOME_CLASS_H
          #define SOME_CLASS_H
          
          class SomeClass {
          private:
              int m_x;
          
          public:
              SomeClass();
              explicit SomeClass( x = 0 );
          
              void setX( int x );
              int  getX() const;
          
          private:
              SomeClass( const SomeClass& c ); // Not Implemented - Copy Constructor
              SomeClass& operator=( const SomeClass& c ); Not Implemented - Overloaded Operator=
          };  // SomeClass
          
          #endif // SOME_CLASS_H
          

          SomeClass.cpp

          #include "SomeClass.h"
          
          // SomeClass() - Default Constructor
          SomeClass::SomeClass() :
          m_x( x ) {
          } // SomeClass
          
          // SomeClass() - Constructor With Default Parameter
          SomeClass::SomeClass( int x ) :
          m_x( x ) {
          } // SomeClass
          
          // setX()
          void SomeClass::setX( int x ) {
              m_x = x;
          } // setX
          
          // getX()
          void SomeClass::getX() const {
              return m_x;
          } // getX
          

          使用动态内存的旧方法

          #include <iostream>
          #include "SomeClass.h"
          
          int main() {
              // Single Dynamic Pointer
              SomeClass* pSomeClass = nullptr;
          
              pSomeClass = new SomeClass( 5 );
          
              std::cout << pSomeClass->getX() << std::endl;
          
              delete pSomeClass;
              pSomeClass = nullptr;
          
              // Dynamic Array 
              SomeClass* pSomeClasses = nullptr;
              pSomeClasses = new SomeClasses[5](); // Default Constructor Called
          
          
              for ( int i = 0; i < 5; i++ ) {
                  pSomeClasses[i]->setX( i * 10 );
                  std::cout << pSomeSomeClasses[i]->getX() << std::endl;
              }
          
              delete[] pSomeClasses;
              pSomeClasses = nullptr;  
          
              return 0;
          } // main
          

          这里的问题是知道何时、何地以及为什么要删除内存;知道谁负责。如果您删除内存来管理它,而您的代码或库的用户认为您没有删除它,那么就会出现问题,因为同一块内存正试图被删除两次。如果您将其留给用户删除它并且他们认为您这样做了并且他们没有您有问题并且存在内存泄漏。这就是使用智能指针派上用场的地方。

          智能指针版本

          #include <iostream>
          #include <memory>
          #include <vector>
          #include "SomeClass.h"
          
          int main() {
              // SHARED POINTERS
              // Shared Pointers Are Used When Different Resources Need To Use The Same Memory Block
              // There Are Different Methods To Create And Initialize Shared Pointers
              auto sp1 = std::make_shared<SomeClass>( 10 );
          
              std::shared_ptr<SomeClass> sp2( new SomeClass( 15 ) );
          
              std::shared_ptr<SomeClass> sp3;
              sp3 = std::make_shared<SomeClass>( 20 );
          
              std::cout << "SP1: " << sp1->getX() << std::endl;
              std::cout << "SP2: " << sp2->getX() << std::endl;
              std::cout << "SP3: " << sp3->getX() << std::endl;
          
              // Now If you Reach The Return Of Main; These Smart Pointers Will Decrement
              // Their Reference Count & When It Reaches 0; Its Destructor Should Be
              // Called Freeing All Memory. This Is Safe, But Not Guaranteed. You Can
              // Release & Reset The Memory Your Self.
          
              sp1.reset();  
              sp1 = nullptr;
          
              sp2.reset();
              sp2 = nullptr;
          
              sp3.reset();
              sp3 = nullptr;
          
              // Need An Array Of Objects In Dynamic Memory?
              std::vector<std::shared_ptr<SomeClass>> vSomeClasses;
              vSomeClasses.push_back( std::make_shared<SomeClass>( 2 ) );
              vSomeClasses.push_back( std::make_shared<SomeClass>( 4 ) );
              vSomeClasses.push_back( std::make_shared<SomeClass>( 6 ) );
          
              std::vector<std::shared_ptr<SomeClass>> vSomeClasses2;    
              vSomeClasses2.push_back( std::shared_ptr<SomeClass>( new SomeClass( 3 ) ) );
              vSomeClasses2.push_back( std::shared_ptr<SomeClass>( new SomeClass( 5 ) ) );
              vSomeClasses2.push_back( std::shared_ptr<SomeClass>( new SomeClass( 7 ) ) );
          
              // UNIQUE POINTERS
              // Unique Pointers Are Used When Only One Resource Has Sole Ownership.
              // The Syntax Is The Same For Unique Pointers As For Shared Just Replace
              // std::shared_ptr<SomeClass> with std::unique_ptr<SomeClass> &
              // replace std::make_shared<SomeClass> with std::make_unique<SomeClass>
              // As For Release Memory It Is Basically The Same
              // The One Difference With Unique Is That It Has A Release Method Where Shared Does Not.
          
              auto mp1 = std::make_unique<SomeClass>( 3 );
              mp1.release();
              mp1.reset();
              mp1 = nullptr;
          
              // Now You Can Also Do This:
              // Create A Unique Pointer To An Array Of 5 Integers
              auto p = make_unique<int[]>( 5 );
          
              // Initialize The Array
              for ( int i = 0; i < 5; i++ ) {
                  p[i] = i;
              }
          
              return 0;
          } // main
          

          这里是共享指针和唯一指针的参考链接

          https://msdn.microsoft.com/en-us/library/hh279669.aspx

          https://msdn.microsoft.com/en-us/library/hh279676.aspx

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-09-28
            • 2018-09-26
            • 1970-01-01
            • 2015-03-09
            • 2010-12-05
            • 2018-05-01
            相关资源
            最近更新 更多