如何抑制类型的自动初始化和破坏?尽管T buffer[100]自动初始化buffer的所有元素并在它们超出范围时将其销毁是一件很了不起的事情,但这不是我想要的行为。

#include <iostream>

static int created   = 0,
           destroyed = 0;

struct S
{
    S()
    {
        ++created;
    }
    ~S()
    {
        ++destroyed;
    }
};

template <typename T, size_t KCount>
class fixed_vector
{
private:
    T m_buffer[KCount];
public:
    fixed_vector()
    {
        // some way to suppress the automatic initialization of m_buffer
    }

    ~fixed_vector()
    {
        // some way to suppress the automatic destruction of m_buffer
    }
};

int main()
{
    {
        fixed_vector<S, 100> arr;
    }

    std::cout << "Created:\t"   << created   << std::endl;
    std::cout << "Destroyed:\t" << destroyed << std::endl;
    return 0;
}

该程序的输出为:
Created:    100
Destroyed:  100

我希望它是:
Created:    0
Destroyed:  0

我唯一的想法是使m_buffer成为某种琐碎构造和破坏的类型,例如char,然后依靠operator[]为我包装指针数学,尽管这似乎是一个骇人听闻的解决方案。另一种解决方案是使用mallocfree,但这提供了我不希望的间接级别。

我之所以想这样做,是因为我在制造一个容器,并且不想为我不使用的东西支付初始化开销。例如,如果我的main函数是:
int main()
{
    {
        std::vector<S> vec;
        vec.reserve(50);
    }

    std::cout << "Created:\t"   << created   << std::endl;
    std::cout << "Destroyed:\t" << destroyed << std::endl;
    return 0;
}

输出将是正确的:
Created:    0
Destroyed:  0

最佳答案

您可以将数组创建为char的数组,然后在需要时使用placement new 创建元素。

template <typename T, size_t KCount>
class Array
{
private:
    char m_buffer[KCount*sizeof(T)]; // TODO make sure it's aligned correctly

    T operator[](int i) {
        return reinterpret_cast<T&>(m_buffer[i*sizeof(T)]);
    }

重新阅读您的问题后,您似乎想要一个稀疏数组,有时有时将其称为map; o)(当然,性能特征是不同的...)
template <typename T, size_t KCount>
class SparseArray {
    std::map<size_t, T> m_map;
public:
    T& operator[](size_t i) {
        if (i > KCount)
            throw "out of bounds";
        return m_map[i];
    }

10-07 19:26
查看更多