new char[n]
和new (char[n])
之间有什么区别吗?
我在生成的代码中有第二种情况,g ++(4.8.0)给了我
ISO C++ does not support variable-length array types [-Wvla]
这让我想到这两者是否相同。
new char[n]
表示“分配n
类型的char
个对象。new (char[n])
是否意味着“分配1 array of n chars
类型的对象”?delete
或delete[]
代码由第三方软件生成(并由软件的其他部分使用),因此我不能只是“使用向量”。
这是最小的例子:
int main (void)
{
int n(10);
int *arr = new (int[n]); // removing parentheses fixes warning
*arr = 0; // no "unused variable" warning
return 0;
}
答案 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[]
,p1
和p2
的初始化都是等效的,并且在所有情况下p3
都是正确的释放形式。
delete[]
的初始化有效,但p4
和p5
的代码不正确C ++。不使用p6
时,g ++会允许它们,并且通过类比我希望-pedantic
,p4
和p5
的初始化也是等价的。 @ 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}}