为什么这是一个错误:
typedef int H[4];
H * h = new H; // error: cannot convert 'int*' to 'int (*)[4]' in initialization
Run Code Online (Sandbox Code Playgroud)
?
此外,为什么这不是一个错误:
H * h = new H[1];
Run Code Online (Sandbox Code Playgroud)
?
为什么编译器认为new H返回an int *,而new H[1]返回an H *按预期?
换句话说:为什么T * t = new T;普通类型T是正确的,但是当T数组类型不正确时?
分配简单数组类型的规范方法是new什么?
请注意,这是一个简化的示例,因此例如new int[4]不是可接受的解决方法 - 我需要使用前面的实际类型typedef.
另请注意,我知道,使用std::vector,std::array,等人一般都在C风格数组更好,但我有一个"真实世界"的使用情况下,我需要与类型的合作,如上述.
Rei*_*ica 15
返回类型和值的C++规则new T是:
T不是数组类型,则返回类型为T *,并且返回的值是指向动态分配的类型对象的指针T.T是类型的数组U,则返回类型为U *,并且返回的值是指向U动态分配的类型数组的第一个元素(其类型为)的指针T.因此,既然你H是一个数组int,返回类型new H是int *,不是H *.
按照相同的规则,new H[1]返回H *,但请注意,您已经技术分配了一个二维数组的ints,大小为1 x 4.
在通用代码中解决此问题的最佳方法确实是使用auto:
auto h = new H;
Run Code Online (Sandbox Code Playgroud)
或者,如果您希望突出显示指针事实:
auto *h = new H;
Run Code Online (Sandbox Code Playgroud)
至于规则中看似不一致的基本原理:指向数组的指针在C++中非常"危险",因为它们表现得非常意外(即你必须非常小心它们才能产生不必要的效果).我们来看看这段代码:
typedef int H[4];
H *h = obtain_pointer_to_H_somehow();
h[2] = h[1] + 6;
Run Code Online (Sandbox Code Playgroud)
在第一次(甚至可能是第二次)一瞥时,上面的代码似乎int在数组中将第二个加到第二个并将其存储在第三个中int.但这不是它的作用.
就像是int *p,p[1]是一个int(在地址sizeof(int)字节偏移p),所以for H *h,h[1]是一个H,在地址4 * sizeof(int)字节偏移距离h.因此代码被解释为:取入地址h,4 * sizeof(int)向其中添加字节,然后添加6,然后将生成的地址存储在偏移量8 * sizeof(int)处h.当然,这将失败,因为h[2]衰退到右值.
好的,你修复它像这样:
*h[2] = *h[1] + 6;
Run Code Online (Sandbox Code Playgroud)
现在更糟糕了.[]结合更紧相比*,因此这将伸入5日int之后的对象h(注意,只是其中的4有!),加上6,并编写成9日int之后h.写入随机存储器FTW.
要实际执行代码可能的目的,它必须拼写如下:
(*h)[2] = (*h)[1] + 6;
Run Code Online (Sandbox Code Playgroud)
鉴于上述情况,并且由于您通常使用动态分配的数组来访问其元素,因此new T[]返回更有意义T *.
| 归档时间: |
|
| 查看次数: |
1293 次 |
| 最近记录: |