新char [n]和new(char [n])之间的差异

时间:2013-05-19 12:37:41

标签: c++ memory-management

new char[n]new (char[n])之间有什么区别吗?

我在生成的代码中有第二种情况,g ++(4.8.0)给了我

ISO C++ does not support variable-length array types [-Wvla]

这让我想到这两者是否相同。

  1. new char[n]表示“分配n类型的char个对象。
  2. new (char[n])是否意味着“分配1 array of n chars类型的对象”?
  3. 删除第一个很清楚。
  4. 我应该使用deletedelete[]
  5. 删除第二个
  6. 我应该注意哪些其他差异?
  7. 我可以安全地删除括号并将第二种情况转换为第一种情况,当软件的其他部分期望第二种情况时?
  8. 代码由第三方软件生成(并由软件的其他部分使用),因此我不能只是“使用向量”。

    这是最小的例子:

    int main (void)
    {
        int n(10);
        int *arr = new (int[n]); // removing parentheses fixes warning
        *arr = 0; // no "unused variable" warning
        return 0;
    }
    

3 个答案:

答案 0 :(得分:10)

这里的基本问题是C ++不允许在类型中使用数组绑定[n],除非n是常量表达式。 g ++和其他一些编译器有时会允许它,但是当你开始混合变长数组和模板时,不可能得到一致的行为。

明显异常int* p = new int[n];有效,因为此处[n]在语法上是new表达式的一部分,而不是提供给new的类型的一部分,{{1 “知道如何”创建长度在运行时确定的数组。

new

从语义上讲,在使用任何最终// can be "constexpr" in C++11: const int C = 12; int main() { int* p1 = new int[C]; int* p2 = new (int[C]); typedef int arrtype[C]; int* p3 = new arrtype; int n = 10; int* p4 = new int[n]; // int* p5 = new (int[n]); // Illegal! // typedef int arrtype2[n]; // Illegal! // int* p6 = new arrtype2; delete[] p1; delete[] p2; delete[] p3; delete[] p4; } 将类型转换为数组类型之后,新表达式只关心它是否处理数组。关于表达式类型的所有要求,无论是使用[C]还是new[]等,都说“当分配的类型是数组时”,而不是“当使用数组新语法时” 。因此,在上面的示例中,delete[]p1p2的初始化都是等效的,并且在所有情况下p3都是正确的释放形式。

delete[]的初始化有效,但p4p5的代码不正确C ++。不使用p6时,g ++会允许它们,并且通过类比我希望-pedanticp4p5的初始化也是等价的。 @ MM的反汇编支持这个结论。

所以是的,从这种表达式中删除“额外”括号应该是一种安全的改进。正确的删除是p6类型。

答案 1 :(得分:6)

  • new T[N]生成N类型的T元素数组。

  • new (T[N])生成T[N]类型的单个对象。

效果相同(两个表达式都产生一个T *,指向数组的第一个元素,需要用delete[]删除(参见5.3.4 / 5),但是在后一种情况下,T[N]必须是有效的类型,因此N必须是常量表达式,而在前一种情况下,它是数组的动态参数表达

答案 2 :(得分:3)

  new int [n]
  //Allocates memory for `n` x `sizeof(int)` and returns
  //the pointer which points to the beginning of it. 

 +-----+-----+-----+-----+-----+-----+-----+-----+------+------+
 |     |     |     |     |     |     |     |     |      |      |
 |     |     |     |     |     |     |     |     |      |      |
 |     |     |     |     |     |     |     |     |      |      |
 +-----+-----+-----+-----+-----+-----+-----+-----+------+------+


  new (int [n])
  //Allocate a (int[n]), a square which its item is an array
+----------------------------------------------------------------+
|+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
||     |     |     |     |     |     |     |     |      |      | |
||     |     |     |     |     |     |     |     |      |      | |
||     |     |     |     |     |     |     |     |      |      | |
|+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
+----------------------------------------------------------------+

事实上两者都是平等的。

这是汇编程序生成的代码(只是一个可忽略的区别):

int n = 10;
int *i = new (int[n]);
int *j = new int[n];

i[1] = 123;
j[1] = 123;

----------------------------------

!    int *i = new (int[n]);
main()+22: mov    0x1c(%esp),%eax
main()+26: sub    $0x1,%eax
main()+29: add    $0x1,%eax
main()+32: shl    $0x2,%eax
main()+35: mov    %eax,(%esp)
main()+38: call   0x401620 <_Znaj> // void* operator new[](unsigned int);
main()+43: mov    %eax,0x18(%esp)
!    int *j = new int[n];
main()+47: mov    0x1c(%esp),%eax
main()+51: shl    $0x2,%eax
main()+54: mov    %eax,(%esp)
main()+57: call   0x401620 <_Znaj> // void* operator new[](unsigned int);
main()+62: mov    %eax,0x14(%esp)
!    
!    i[1] = 123;
main()+66: mov    0x18(%esp),%eax
main()+70: add    $0x4,%eax
main()+73: movl   $0x7b,(%eax)
!    j[1] = 123;
main()+79: mov    0x14(%esp),%eax
main()+83: add    $0x4,%eax
main()+86: movl   $0x7b,(%eax)

您必须delete

delete [] ...这两个人{{1}}