我需要一个既不可复制也不可移动的元素容器.这些元素不是默认可构造的,但它们的构造函数获得相同的参数.
容器的大小在其生命周期内不会改变.它应该像内置数组一样简单,但它的大小是在调用构造函数时在运行时确定的.
是否有一种简单的方法来实现它,而不会因使用std :: vector< std :: unique_ptr< T>>?而导致内存分配和间接开销.
最佳答案 在假设每个元素都使用相同的参数构造的情况下,这是一个简单但不完整的解决方案.它使用
placement new
来就地构建元素(参见
this SO question):
#include <cstdlib>
#include <utility>
#include <new>
// sample structure, non-copyable, non-moveable, non-default-constructible
struct Foo
{
Foo() = delete;
Foo(const Foo&) = delete;
Foo& operator = (const Foo&) = delete;
Foo(Foo&&) = delete;
Foo& operator = (Foo&&) = delete;
Foo(int a, char b, double c) : m_a(a), m_b(b), m_c(c) { }
int m_a;
char m_b;
double m_c;
};
template <typename T>
struct MyArray
{
// Array ctor constructs all elements in-place using the
// provided parameters
template <typename... Args>
MyArray(std::size_t sz, Args&&... args)
: m_sz(sz),
m_data(static_cast<T*>(malloc(sz * sizeof(T))))
{
for (std::size_t i=0; i<m_sz; ++i)
{
new (&m_data[i]) T(std::forward<Args>(args)...);
}
}
~MyArray()
{
for (std::size_t i=0; i<m_sz; ++i)
{
m_data[i].~T();
}
free(m_data);
}
std::size_t m_sz;
T *m_data;
};
int main()
{
Foo foo(1, '2', 3.0);
std::size_t s = 5;
MyArray<Foo> foo_arr(s, 1, '2', 3.0);
}
请注意,缺少一些东西:
>如果在MyArray的构造函数中抛出异常,则此基本实现将泄漏内存.
>您可能需要迭代器实现,begin()/ end()运算符等,以获得更多便利并获得与标准容器提供的相同的行为.
>为了便于说明,我也没有适当的封装.你应该把m_sz和m_data私有成员.