[解决办法] operator new (sizeof(A) * 10) 不带类型的分配(sizeof(A)里面的A是不会反映到new的类型的,仅仅代表了大小信息),其实等同于 new BYTE [sizeof(A) * 10];默认的对象对齐以字节类型为准而不是待分配的类类型要求的基址对齐方式 [解决办法]
operator new (sizeof(A) * 10) 不带类型的分配(sizeof(A)里面的A是不会反映到new的类型的,仅仅代表了大小信息),其实等同于 new BYTE [sizeof(A) * 10];默认的对象对齐以字节类型为准而不是待分配的类类型要求的基址对齐方式
不对吧,sizeof(A)本身的大小,就已将对齐考虑在内了 [解决办法] std::vector/std::array [解决办法] 如果你定义的数组的对象类型有默认构造函数,那么恭喜你,在数组用到的时候初始化自动完成; 如果没有的话,比如有一个单参数的构造函数,那么你必须显式调用。比如 class A { private: int a; public: A(aa):a(aa){} };
A arr[2] = { A(1), A(2) }; 希望对你有所帮助
[解决办法]
operator new (sizeof(A) * 10) 不带类型的分配(sizeof(A)里面的A是不会反映到new的类型的,仅仅代表了大小信息),其实等同于 new BYTE [sizeof(A) * 10];默认的对象对齐以字节类型为准而不是待分配的类类型要求的基址对齐方式
不对吧,sizeof(A)本身的大小,就已将对齐考虑在内了
sizeof(A)只是一个整数了。不会决定new返回的指针的对齐。比如下面这个例子
#include <iostream>
class A { private : long long _n; public: A( long long n):_n(n) {} };
int main() { A *pA = (A*) operator new (sizeof(A) * 10); for(int i = 0; i != 10; ++i) { new (pA + i) A(i); } }
sizeof(A)等于8,这样new执行的时候相当于 operator new (80); 而他的返回值在32位系统中默认对齐为4,也就是整个new在你强制转换成A*之前的返回值是被4整除的,实际上按语法看的话甚至有可能仅是1,也就是完全不考虑对齐。而A对象要求以8为整个对象的对齐,也就是整个new在你强制转换成A*之前的返回值能被8整除。如果是new A的话,(void *)new A的结果保证能被8整除而如果系统找不到这样的空闲地址区域的话宁可失败,而不是返回一个没有对齐的地址。而这样的约束对于(void *)operator new (80);却并不成立。 你说的A“已经考虑了对齐”其实应该指的仅是成员相对于对象基址的对齐,也就是说如果A是这样的: class A { char m1; int m2; }; 那么在m1到m2之间会有诺甘个字节的空缺(共sizeof(int)-1个字节)而不是让m2紧挨着m1存放。 但是涉及到内存分配,不管是直接定义也好还是用new分配,不光需要你说的这种对齐,而且还需要整个对象的基地址的对齐。这样才能最终做到每个成员在运行时真正的对齐。如果是直接定义或者用new类型的分配方式,这总是可以保证;但是去掉类型信息分配的话就没有这种保证了 [解决办法] 还有A本身的大小问题,大小对齐正是为了在定义数组的时候不至于存在部分数组元素没有对齐的问题。比如 class A { char m1; int m2; char m3; }; 如果是为了压缩空间,完全可以让sizeof(A)等于9。但是这样一来如果定义A a[4];的话将会出现除了a[0]其余元素都未有对齐的情况。所以A的末尾也补一些字节从而让sizeof(A)等于3个int的字节大小