有人能告诉我这两行C ++代码有什么区别吗?
int *p = new int (7);
和
int *p = new int [7];
除了在第一个中将数字7放在p [0]中之外,我无法发现任何差异,还有其他区别吗?如果会有char而不是int会发生什么?
提前致谢。
答案 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
研究术语 - 退化指针