如何抑制类型的自动初始化和销毁? 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[]
来包装指针数学对我来说,虽然这似乎是一个可怕的黑客解决方案。另一种解决方案是使用 malloc
和 free
,但这提供了我不想要的间接级别。
我想要这个的原因是因为我正在制作一个容器,我不想为我不会使用的东西支付初始化开销。例如,如果我的 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
最佳答案
你可能想看看 boost::optional
template <typename> struct tovoid { typedef void type; };
template <typename T, size_t KCount, typename = void>
struct ArrayStorage {
typedef T type;
static T &get(T &t) { return t; }
};
template <typename T, size_t KCount>
struct ArrayStorage<T, KCount, typename tovoid<int T::*>::type> {
typedef boost::optional<T> type;
static T &get(boost::optional<T> &t) {
if(!t) t = boost::in_place();
return *t;
}
};
template <typename T, size_t KCount>
class Array
{
public:
T &operator[](std::ptrdiff_t i) {
return ArrayStorage<T, KCount>::get(m_buffer_[i]);
}
T const &operator[](std::ptrdiff_t i) const {
return ArrayStorage<T, KCount>::get(m_buffer_[i]);
}
mutable typename ArrayStorage<T, KCount>::type m_buffer_[KCount];
};
对类类型进行了专门化,将它们包装到一个optional
中,从而延迟调用构造函数/析构函数。对于非类类型,我们不需要包装。不包装它们意味着我们可以将 &a[0]
视为连续的内存区域,并将该地址传递给需要数组的 C 函数。 boost::in_place
将就地创建类类型,而不使用临时的 T
或其复制构造函数。
不使用继承或私有(private)成员允许类保持聚合,允许一种方便的初始化形式
// only two strings are constructed
Array<std::string, 10> array = { a, b };
关于C++ 禁止自动初始化和销毁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2662417/