如何抑制类型的自动初始化和销毁?虽然这很美妙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
and 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
或其复制构造函数。
不使用继承或私有成员允许类保持聚合,从而允许方便的初始化形式
// only two strings are constructed
Array<std::string, 10> array = { a, b };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)