放置新的奇怪行为

Placement new strange behaviours

本文关键字:      更新时间:2023-10-16

不要问我想做什么,这只是一个快速测试,它的唯一目的是看看是否有一些错误的位置新的

我发现了一个问题,或者是我误解了什么。

#include <vector>
using namespace std;
#define WORKS 
int main(int argc, char** argv) {
    vector<int>* pp = (vector<int>*)malloc(sizeof(vector<int>)*20);
#ifdef WORKS
    for(int i = 0; i < 20; ++i)
    new (pp+i) vector<int>;
#else
    new (pp) vector<int>[20];
#endif
    for(int i = 0; i < 20; ++i) 
        pp[i].~vector<int>();
}

当你删除"#define WORKS"时,它会给你访问冲突,如

    for(int i = 0; i < 20; ++i)
    new (pp+i) vector<int>;

效果很好,与

不同
    new (pp) vector<int>[20];

是在销毁阶段抛出异常的原因。这是怎么回事?我正在使用Windows XP和vc++ Express 2010构建。

§5.3.4/12:

——new T[5]导致调用operator new[](sizeof(T)*5+x)

[…)

这里,x和y是非负的未指定值,表示数组分配开销;new-表达式的结果将从new[]操作符返回的值中偏移这一量。这个开销可以应用在所有数组new-expressions中,包括引用标准库函数operator new[](std::size_t, void*)和其他位置分配函数。开销的数量可能因每次调用new而异。[强调添加]

总而言之,尝试放置数组可能需要一些未指定数量的开销,而这些开销不是您分配的。只要单独放置元素,就不允许这样的开销,因此放置new就可以了。

new表达式的结果不必与传递给置换new操作符的地址相同。而且,不能保证分配数组所需的大小严格等于单个元素的大小乘以元素的数量。

5.3.4:

A new-expression传递数量请求分配的空间的大小函数作为类型的第一个参数std::size_t。这个论点应该是不小于物体的大小创建;可能更大而不是物体的大小仅当对象是数组 .

因此,更正确的代码版本应该是:
     void *ppstorage= malloc(sizeof(vector<int>)*20);
    pp= new (ppstorage) vector<int>[20];
    for(int i = 0; i < 20; ++i) 
        pp[i].~vector<int>();

虽然你几乎肯定会写在ppstorage的末尾。编译器必须将数组的计数存储在某个地方,以便正确地析构每个元素,对于存储在new表达式返回的地址之前的MSVC,

理论上,可以重载operator new[]来获得数组的实际分配大小:

void *operator new[](size_t *allocation_size, size_t size)
{
    *allocation_size= size;
    return nullptr;
}

当您使用operator new[]时,您必须释放operator delete[]。您不能使用new[]进行分配,然后逐个释放。所以你可以这样做,而不是你的回收循环:

delete [] pp;
相关文章:
  • 没有找到相关文章