简体   繁体   English

在堆上声明一个数组

[英]Declaring an array on the heap

When I am declaring an array on the heap, which method is better? 当我在堆上声明一个数组时,哪种方法更好? For simplicity and example's sake the private data is made public here. 为了简单起见,在此将私有数据公开。

Should I create a new pointer, modify data, and then 我应该创建一个新的指针,修改数据,然后

CAT *Family = new CAT[2];

for(int i=0; i<2;i++){
    Family[i].age = i+1;
}

VS VS

CAT *Family = new CAT[2];
CAT *pCat;


for(int i=0; i<2;i++){
    pCat = new CAT;
    pCat->age = i+1;
    Family[i] = *pCat;
    delete pCat;
}

It's generally not a good idea to use raw pointers and new directly. 通常,直接使用原始指针和new并不是一个好主意。

The less of that, the better. 越少越好。

Instead, to create your array on the heap, do this: 相反,要在堆上创建数组,请执行以下操作:

std::vector<Cat> cats( 2 );
for( int i = 0; i < int( cats.size() ); ++i ){
    cats[i].age = i+1;
}

or alternatively, this: 或者,这是:

std::vector<Cat> cats;
for( int i = 0; i < 2; ++i ){
    cats.emplace_back( i+1 );
}

The direct use of raw arrays and new indicates a C programmer or incompetent, since std::vector is in the C++ standard library precisely for this purpose, taking care of correct memory management. 直接使用原始数组和new表示C程序员或不称职的C,因为std::vector正是出于此目的而在C ++标准库中,并负责正确的内存管理。


Note also that ALL UPPERCASE names are a convention used for macros. 还要注意,所有大写名称都是用于宏的约定。 The idea is to minimize the chance of name collisions and inadvertent text substitution. 这样做的目的是最大程度地减少名称冲突和文本替换的可能性。 When you use such names for other things, you instead increase the chance of name collisions and inadvertent text substitution, not to mention that many programmers read all uppercase as shouting, extra strong emphasis. 当您将此类名称用于其他用途时,您会增加名称冲突和文本替换的可能性,更不用说许多程序员将所有大写字母都大喊大叫,特别强调。

The first approach has a definite advantage in terms of number of times the Constructor is called. 就构造器被调用的次数而言,第一种方法具有明显的优势。 For your trivial example, its fine. 对于您的小例子,它很好。 However, assume a class that does heavy resource allocation in c'tor and frees them in d'tor. 但是,假定一个类在c'tor中分配大量资源并在d'tor中释放它们。 The second approach would call these c'tors and d'tor 2 times extra which is a heavy penalty. 第二种方法将这些c'tors和d'tors称为额外的2倍,这是很重的惩罚。 #include using namespace std; #include使用命名空间std;

class CAT{
public:
 CAT(){ cout<<"c'tor called"<<endl;}
 int age;
 ~CAT(){ cout<<"d'tor called"<<endl;}
};

main(){
  CAT *Family= new CAT[2];
  CAT *pCat;

  for(int i=0; i<2;i++){
    pCat = new CAT;
    pCat->age = i+1;
    Family[i] = *pCat;
    delete pCat;
  } 
}

Run it 

$./a.out 
c'tor called
c'tor called
c'tor called
d'tor called
c'tor called
d'tor called

Your second implementation is going allocate more variables on the stack and is going to require more complex assembly code (I remember having to generate assembly code for the above code for a C style language, and it get's harry!). 您的第二种实现是在堆栈上分配更多变量,并且需要更复杂的汇编代码(我记得必须为上述代码为C样式语言生成汇编代码,这很麻烦!)。 For bonus points, if you're looking for optimizations, I suggest you use a pre-increment in your for loop ;) 为了获得加分,如果您正在寻找优化,建议您在for循环中使用预递增 ;)

I don't see any advantage to the firs method if you are trying to create an array of objects. 如果您尝试创建对象数组,则认为firs方法没有任何优势。 However, the second method would be necessary if you are trying to create an array of pointers, which could point to different concrete types. 但是,如果您尝试创建一个指针数组,则可能需要第二种方法,该指针数组可能指向不同的具体类型。

struct A
{
   virtual ~A() {}
};

struct B : A
{
   int data;
}

struct C : A
{
   double data;
}


int main()
{
   A* array[20];

   // Get half of the array filled with B*.
   for (int i = 0; i < 10; ++i )
   {
      B* b = new B;
      b.data = i*10;
      array[i] = b;
   }

   // Get the other half of the array filled with C*.
   for (int i = 10; i < 20; ++i )
   {
      C* c = new C;
      c.data = i*1.5;
      array[i] = c;
   }

   // Delete the objects.
   for (int i = 0; i < 20; ++i )
   {
      delete array[i];
   }

   return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM