64,654
社区成员
发帖
与我相关
我的任务
分享
#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类型的分配方式,这总是可以保证;但是去掉类型信息分配的话就没有这种保证了
#include <iostream>
class A
{
private :
int _n;
public:
A( int 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);
}
}