声明数组时,[]和()之间的C ++差异

时间:2015-07-05 15:02:17

标签: c++ arrays declaration

有人能告诉我这两行C ++代码有什么区别吗?

int *p = new int (7);

int *p = new int [7];

除了在第一个中将数字7放在p [0]中之外,我无法发现任何差异,还有其他区别吗?如果会有char而不是int会发生什么?

提前致谢。

4 个答案:

答案 0 :(得分:4)

一个是7个项目的数组

new int [7]

另一个只是初始化一个指向int的指针,其值为7

答案 1 :(得分:4)

int *p = new int (7);

一块一块地看着它:int *p创建一个指向int的指针。 new int (7)在堆上创建一个新的int,并将值7存储在那里。 =告诉计算机p应该指向新创建的int的地址。

int *p = new int [7];

再次,一点一点地采取它:我们已经知道int *p创建一个指向int的指针。 new int [7]创建了一个int的数组。该数组的大小为7,因此计算机为7个整数设置了内存空间。在这种情况下,=告诉指针它应该指向数组的开头,也就是说,它将指向那些int中的第一个。

当您使用方括号[i]和指针时,例如p[i]您告诉计算机为您提供p指向的内存地址但i偏移的内容。当p指向数组的开头时,您可以使用p[i]访问数组的不同部分。但如果p指向单个int,p[i]没有意义,所以它是未定义的。一个可能的结果是它只会偏移内存地址,并为您提供存储在int旁边的内存中的任何内容,但行为未定义,因此不同的编译器,计算机,操作系统/任何可能导致不同的结果。

答案 2 :(得分:3)

第一个只创建一个int,而不是数组。试图访问超出它的任何东西,例如p[1],是未定义的行为。

答案 3 :(得分:1)

  

不幸的是,我可以访问p [i] 0上有值   那里...... - Raz Ben Netanel 29分钟前

所以这是你的下一个实验 - 但这只是一个学习练习!像往常一样,你不应该在家里试试。

int t213(void)
{
   // let me create an array of ints on the stack
   int  buff[128];
   // and initialize them to a distinctive patterh
   for (int i=0; i<128; i++) buff[i] = 0x55555555;

   void* place0 = buff; // offset 0 into buff

   // if you want, try printing buff[0] (and maybe 1 or 2 more) 
   // use hex to see the 55555555 pattern

   // next I use placement new to do something that makes everyone
   // (familiar with UB) uncomfortable ... Relax, I have an embedded 
   // software background and understand that the behavior we shall 
   // observe is not guaranteed, not even from 1 compile to the next

   int* p1 = new (place0) int(7);  // a single int, initialized to 7, 
   void* p1Addr = p1;              // at location place0

   // (no - I know your thinking about it, but don't do this.  
   // essentially because neither C nor C++ have memory layout symantics.)

   dtbAssert(p1Addr == place0)(p1Addr)(place0); // no assert occurs
                                                // both addresses are the same

   // test the soup
   std::cout << "\np1      : " << std::setw(12) << std::hex << *p1     << "  @" << DTB::hexComma(p1Addr)
             << "\nbuff[0] : " << std::setw(12) << std::hex << buff[0] << "  @" << DTB::hexComma(&buff[0])
             << "\nbuff[1] : " << std::setw(12) << std::hex << buff[1] << "  @" << DTB::hexComma(&buff[1])
             << std::endl;

   // now spoil the soup:
   p1[1] = 0xdeadbeef; // oops - UB   NO COMPILER WARNING

   // then test the soup once more
   std::cout << "\np1      : " << std::setw(12) << std::hex << *p1     << "  @" << DTB::hexComma(p1Addr)
             << "\nbuff[0] : " << std::setw(12) << std::hex << buff[0] << "  @" << DTB::hexComma(&buff[0])
             << "\nbuff[1] : " << std::setw(12) << std::hex << buff[1] << "  @" << DTB::hexComma(&buff[1])
             << std::endl;

   return(0);
}

由于我使用了一些私有工具,我将包含输出:

p1      :            7  @7ffe,c3bb,3910
buff[0] :            7  @7ffe,c3bb,3910
buff[1] :     55555555  @7ffe,c3bb,3914

p1      :            7  @7ffe,c3bb,3910
buff[0] :            7  @7ffe,c3bb,3910
buff[1] :     deadbeef  @7ffe,c3bb,3914

请注意标有注释“// oops - UB”的代码行。

该行使用p1 [1]。但编译器没有注意到越界索引 - 甚至没有警告。

因为它是UB,所以编译器生成了它想要的东西。在这种情况下(但不保证),就好像p1 [1]存在 - 注意buff [1]从55555555变为deadbeef

研究术语 - 退化指针