placement new(ptr) 地址偏移了4字节,为什么呢

downmooner 2011-03-31 10:36:45
class A
{
public:
A()
{
m_str ="dsfds";
}
void set(string s)
{
m_str = s;
}
string str()
{
return m_str;
}
virtual ~A()
{
m_str="1";
}
private:
string m_str;
};

struct B{
B()
{
i = 100;
}
B(int b)
{
i = b;
}
int i;

//这里
char buff[1000];

A* p = new(buff)A[6];

//我本以为p的数值应该和buff的一样,但p比buff大4.但实际上buff的前4字节的内存没被修改过。

//而把A换成B,p就等于buff了

//现在总结是pod类型就不加4。

//群里有人说关键字是uninitialized_fill,但我看了代码,没发现有哪指针偏移的操作

};



请大家解惑
...全文
356 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
LZ如果你是内存池,在malloc一块大内存的时候就已经记录了分配的大小的,至于你里面的小内存不需要记录,因为释放是整体释放的。哎,不说了。该怎么着就怎么着把。
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 downmooner 的回复:]
这个是最小的4字节。
char buff[1000] 地址也是4的整数倍。一样还是+4了[/Quote]
因为对齐的调整不是说你目前的地址是size的整数倍就不调整了。大概是用下面代码来调整的。主要在第2行代码。
int a =12;
int b=(12+sizeof(a))&~(sizeof(a)-1);
我这里假设地址是12,正常来说可以在这个起始地址上构造一个int但是你看调整后的地址编程多少了是16。
downmooner 2011-03-31
  • 打赏
  • 举报
回复

。。。结贴。
qq120848369 2011-03-31
  • 打赏
  • 举报
回复
那还是从内存池取出内存以后,逐个对象构造吧,我看STL剖析里没用到这个,contruct之类的,uninitialized_fill都是逐个对象构造的.
downmooner 2011-03-31
  • 打赏
  • 举报
回复
哦。。好像头4字节确实是存了个数。。

我代码刚好不小心写成了 对象size那么大的个数。。所以修改了没看出来。。。。
downmooner 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 pengzhixi 的回复:]

是不是对齐的原因,你用p的地址除以A的size用p的地址除以B的size看余数是否为0
[/Quote]
class A
{
public:
A()
{
m_str = new char[10];
}

~A()
{
delete [] m_str;
}
private:
char* m_str;
};


这个是最小的4字节。
char buff[1000] 地址也是4的整数倍。一样还是+4了
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 downmooner 的回复:]
我用placement new 目的是调用构造函数,但发现我free会内存池的时候错了,就发现这个问题。[/Quote]

额,显示调用析构函数后,还得用原来的指针进行free。因为placement new调整边界的原因。
chenyu2202863 2011-03-31
  • 打赏
  • 举报
回复
对齐
在一些需要小内存的地方,可以用此法,比如boost 的function
,但是,在栈上的内存并没有对齐,这里的情况猜测是编译器导致的。

你可以看看tr1::alignment_of,还有Sutter老兄书里讲placement new的章节
bruceteen 2011-03-31
  • 打赏
  • 举报
回复
因为 char 不需要析构呀,它就没必要保存元素数目。
downmooner 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 pengzhixi 的回复:]

引用 14 楼 bruceteen 的回复:
re downmooner:
我测试的结果是改了,填上了6。当然,改不改都不影响结果,可能你用的编译优化得比较好。
但,前面空余4个字节则是必然的,因为placement new只是重载了内存分配那一块,它没办法更改new[]本身的行为。而new[]本身是需要保存元素数目的(没有析构函数的则不需要)。

placement new不分配内存……
[/Quote]

我用placement new 目的是调用构造函数,但发现我free会内存池的时候错了,就发现这个问题。
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
只是将构造的地址调整到size的整数倍而已。没什么别的。
downmooner 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 bruceteen 的回复:]

re downmooner:
我测试的结果是改了,填上了6。当然,改不改都不影响结果,可能你用的编译优化得比较好。
但,前面空余4个字节则是必然的,因为placement new只是重载了内存分配那一块,它没办法更改new[]本身的行为。而new[]本身是需要保存元素数目的(没有析构函数的则不需要)。
[/Quote]
char buff[1000];

char* p = new(buff)char[6];


p的值和buff 一样。没偏移4字节,为什么呢

我本来是用来改内存池的,buff是自己的内存池空间,我循环了申请了几百M,100W次操作,查看内存布局,
我申请A的时候,buff前4字节确实没变。
qq120848369 2011-03-31
  • 打赏
  • 举报
回复
没用过new[],不知道它会额外记录些什么.
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 bruceteen 的回复:]
re downmooner:
我测试的结果是改了,填上了6。当然,改不改都不影响结果,可能你用的编译优化得比较好。
但,前面空余4个字节则是必然的,因为placement new只是重载了内存分配那一块,它没办法更改new[]本身的行为。而new[]本身是需要保存元素数目的(没有析构函数的则不需要)。
[/Quote]
placement new不分配内存。
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
是不是对齐的原因,你用p的地址除以A的size用p的地址除以B的size看余数是否为0
hastings 2011-03-31
  • 打赏
  • 举报
回复
定位new可以有数组形式的呀?第一次看到
bruceteen 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 mt619722122 的回复:]

类A里有虚函数,对象的开头应该是VPTR,占四个字节,指向虚函数表,类B没有,内存的布局第一个就是数据成员
[/Quote]
即便要保存VPTR,那也在元素内部呀
mt619722122 2011-03-31
  • 打赏
  • 举报
回复
类A里有虚函数,对象的开头应该是VPTR,占四个字节,指向虚函数表,类B没有,内存的布局第一个就是数据成员
bruceteen 2011-03-31
  • 打赏
  • 举报
回复
re downmooner:
我测试的结果是改了,填上了6。当然,改不改都不影响结果,可能你用的编译优化得比较好。
但,前面空余4个字节则是必然的,因为placement new只是重载了内存分配那一块,它没办法更改new[]本身的行为。而new[]本身是需要保存元素数目的(没有析构函数的则不需要)。
downmooner 2011-03-31
  • 打赏
  • 举报
回复
new[] 那偏移了4字节的内存内容 没被修改,所以也不会是记录了多少个对象。
加载更多回复(12)

64,281

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧