我想创建一个简单的模板数组列表类但是当我做类似的事情时
T* typeArray = new T[10];
这会创建 10 个对象实例,调用构造函数 10 次。如果我以后可以放置对象,我该如何创建一个空数组?
这不是在 C++ 中做事的首选方式,但
T* my_array = (T*)malloc(10 * sizeof(T));
更符合标准 C++ 实践的解决方案是
std::vector<T> my_vector;
my_vector.reserve(10);
请注意,(正如评论中提到的)解决方案的reserve
不同之处在于,如果没有进一步的操作my_vector[5]
,则无效,而有效my_array[5]
。您随后将需要类似my_vector.resize(10)
的东西来索引它,这将构建所有 10 个项目。push_back(T const&)
您可以通过执行或从前到后构造它们emplace_back(Args...&& args)
。只有以这种方式构建后,[]
索引才是合法的。作为警告,[]
即使是非法的,索引也可能起作用,但它是未定义的行为。
template<typename T>
struct RawMem {
alignas(T) unsigned char data[sizeof(T)];
T& get_unsafe() { return *reinterpret_cast<T*>(&data[0]); }
T const& get_unsafe() const { return *reinterpret_cast<T const*>(&data[0]); }
template<typename... Args>
void Construct( Args&&... args ) {
new (&data[0]) T( std::forward<Args>(args)... );
}
void Destroy() {
get_unsafe().~T();
}
};
RawMem<std::string>* buff = new RawMem<std::string>[10];
for (int i = 0; i < 10; ++i) {
buff[i].Construct( "bob is your uncle" );
}
for (int i = 0; i < 10; ++i) {
std::cout << buff[i].get_unsafe() << "\n";
}
for (int i = 0; i < 10; ++i) {
buff[i].Destroy();
}
delete buff;
请注意,当调用析构函数时,您完全负责处理,而当不调用时,使用上述模式。
我包括了助手Construct
和Destroy
函数,这样你就不必自己弄乱放置new
等。同样,get_unsafe()
将让您在需要时获得T&
实例。
以上使用 C++11 alignas
,因为在 C++03 中没有办法解决这个问题。