如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?

Sco*_*rta 2 c++ constructor memory-management stl vector

我正在“现代化”一个(相当古老的)C++ 项目,并在这部分绊倒了:

旧代码为动态数组分配内存,然后根据需要稍后为元素调用构造函数。我猜想为所有元素调用构造函数是很昂贵的,所以作者选择了这种方式(性能对于这个项目来说很关键)。旧代码如下(简化):

struct my_struct {
    my_struct(int x, int y, int z) { /* expensive ctor */ }
};

struct other_class {
    my_struct* arr;
    other_class(int n) {        
        arr = (my_struct*) malloc(n * sizeof(arr[0]);
    }

    void foo(int idx, int a, int b, int c) {
        new (&arr[idx]) my_struct(a, b, c);
    }
};
Run Code Online (Sandbox Code Playgroud)

我改arrstd::vector<my_struct>和使用std::reserve“预约”的记忆。代码工作正常,通过了所有当前测试,但我知道这不行,因为std::reserve不会增加该向量的大小,因此调用arr.size()仍将返回 0。这是我的代码:

struct other_class {
    std::vector<my_struct> arr;
    other_class(int n) {        
        arr.reserve(n);
    }

    void foo(int idx, int a, int b, int c) {
        new (&arr[idx]) my_struct(a, b, c);
    }
};
Run Code Online (Sandbox Code Playgroud)

如何使此代码快速且安全(假设我无法向 中添加默认构造函数my_struct)?谢谢你。


编辑:这是示例代码。它按预期编译和运行,没有任何警告:http : //cpp.sh/8ytwf

for*_*818 6

但我知道这不好,因为 std::reserve 不会增加该向量的大小

std::reserve 确实增加了向量容量,并且当您只想分配内存并稍后推送元素时,这正是您想要的。

向量管理的底层数组的大小不等于向量size()size()返回容器中元素的数量,只要没有任何size() == 0.

当你稍后推送元素时,你不需要使用新的放置,但你应该使用push_backemplace_back。更具体地说,这是错误的:

 new (&arr[idx]) my_struct(a, b, c);
Run Code Online (Sandbox Code Playgroud)

因为您访问的向量越界(请记住:大小是元素的数量,容量可以更大,但您不能访问大于向量大小的索引)。反而:

 arr.emplace_back(a,b,c);
Run Code Online (Sandbox Code Playgroud)

  • @Scorta这是未定义的行为。毫无疑问。大小仍然是“0”,你可以产生各种奇怪的效果。例如尝试复制向量 (2认同)