c++ - 存储未初始化的 STL vector ?

我正在编写一个内部循环,需要将 structs 放置在连续存储中。我不知道这些 struct 中有多少会提前。我的问题是 STL 的 vector 将其值初始化为 0,所以无论我做什么,都会产生初始化成本加上设置 struct 成员的成本他们的值(value)观。

有什么方法可以阻止初始化,还是有一个类似 STL 的容器,带有可调整大小的连续存储和未初始化的元素?

(我确信这部分代码需要优化,而且我确信初始化是一笔不小的开销。)

另外,请参阅下面的评论以了解初始化发生的时间。

一些代码:

void GetsCalledALot(int* data1, int* data2, int count) {
    int mvSize = memberVector.size()
    memberVector.resize(mvSize + count); // causes 0-initialization

    for (int i = 0; i < count; ++i) {
        memberVector[mvSize + i].d1 = data1[i];
        memberVector[mvSize + i].d2 = data2[i];
    }
}

最佳答案

std::vector 必须以某种方式初始化数组中的值,这意味着必须调用一些构造函数(或复制构造函数)。 vector(或任何容器类)的行为如果您要访问数组的未初始化部分,就好像它已初始化一样。

最好的办法是使用reserve()push_back(),这样就使用了copy-constructor,避免了default-constructor。

使用您的示例代码:

struct YourData {
    int d1;
    int d2;
    YourData(int v1, int v2) : d1(v1), d2(v2) {}
};

std::vector<YourData> memberVector;

void GetsCalledALot(int* data1, int* data2, int count) {
    int mvSize = memberVector.size();

    // Does not initialize the extra elements
    memberVector.reserve(mvSize + count);

    // Note: consider using std::generate_n or std::copy instead of this loop.
    for (int i = 0; i < count; ++i) {
        // Copy construct using a temporary.
        memberVector.push_back(YourData(data1[i], data2[i]));
    }
}

像这样调用 reserve()(或 resize())的唯一问题是,您最终可能会比您需要的更频繁地调用复制构造函数.如果您可以对数组的最终大小做出很好的预测,最好在开始时将空间 reserve() 一次。但是,如果您不知道最终大小,则至少平均份数会最少。

在当前版本的 C++ 中,内部循环有点低效,因为临时值在堆栈上构造,复制构造到 vector 内存,最后临时值被销毁。然而,下一版本的 C++ 有一个称为 R-Value 引用 (T&&) 的功能,它会有所帮助。

std::vector 提供的接口(interface)不允许其他选项,即使用一些类似工厂的类来构造默认值以外的值。下面是这个模式在 C++ 中实现的粗略示例:

template <typename T>
class my_vector_replacement {

    // ...

    template <typename F>
    my_vector::push_back_using_factory(F factory) {
        // ... check size of array, and resize if needed.

        // Copy construct using placement new,
        new(arrayData+end) T(factory())
        end += sizeof(T);
    }

    char* arrayData;
    size_t end; // Of initialized data in arrayData
};

// One of many possible implementations
struct MyFactory {
    MyFactory(int* p1, int* p2) : d1(p1), d2(p2) {}
    YourData operator()() const {
        return YourData(*d1,*d2);
    }
    int* d1;
    int* d2;
};

void GetsCalledALot(int* data1, int* data2, int count) {
    // ... Still will need the same call to a reserve() type function.

    // Note: consider using std::generate_n or std::copy instead of this loop.
    for (int i = 0; i < count; ++i) {
        // Copy construct using a factory
        memberVector.push_back_using_factory(MyFactory(data1+i, data2+i));
    }
}

这样做确实意味着您必须创建自己的 vector 类。在这种情况下,它也使本来应该是一个简单的例子变得复杂。但有时使用这样的工厂函数可能会更好,例如,如果插入以某个其他值为条件,那么您将不得不无条件地构造一些昂贵的临时函数,即使它实际上并不需要。

关于c++ - 存储未初始化的 STL vector ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/96579/

相关文章:

c++ - 在 getter 函数中返回 const 引用或拷贝?

c++ - C 和 C++ 中的多字 rune 字

c++ - 访问类中定义的 friend 功能

c++ - 为什么这个包含 rand() 的 C++11 代码多线程比单线程慢?

c++ - 打包结构是可移植的吗?

c++ - std::vector 是 `user-defined type` 吗?

c++ - 为什么我们在 C++ 中使用 std::function 而不是原来的 C 函数指针?

c++ - 我们可以有一个虚拟静态方法吗? (c++)

c++ - QObject 多重继承

c++ - 对于所有对象类型 T,sizeof(T) >= alignof(T) 是否总是如此?