所以std :: array和boost :: array(几乎完全相同,我将在下文中简称为“数组”)被设计为为数组提供容器对象,而不会产生向量的开销。如果数组不动态改变大小,则不需要。但是,它们都是通过将数组大小作为构造函数参数而不是模板参数来设计的。结果:vector允许在创建对象后动态调整大小;数组需要在编译时知道大小。
据我所知,如果你有一个数组,你将知道对象创建时的大小但不知道编译时的大小,那么你唯一的选择是1)通过使用vector不必要地产生额外的开销,2)使用(非容器类型)本机数组(例如,int foo[42];
),或者3)从头开始编写自己的数组包装类。这是正确的,这是一个中间的情况,你可能想要使用数组而不是矢量,但不能?或者我能做些什么魔法可能会为我工作?
以下是关于启发这个问题的一些细节(好的,很多),以防它让你理解:
我有一个模块 - 比如调用者 - 将在运行时重复生成二进制数据(unsigned char []或array),然后将其传递给另一个模块 - 比如被调用者。被调用者模块不会修改数组(它会复制并在必要时修改它),因此一旦调用者模块最初创建数组,它就不会改变大小(也不会改变内容)。但是,会出现两个问题:1)每次生成数组时,调用者可能不会生成相同大小的数组 - 它会在创建数组时的rutime时知道数组大小,但不会在编译时知道。 2)调用者将数组传递给被调用者的方法需要能够获取调用者传递给它的任何大小的数组。
我想过让它成为模板化的功能,例如,
template<size_t N> void foo(const array<unsigned char, N>& my_array);
但是,我正在使用接口类将接口与callee模块中的实现分开。因此,该函数必须是一个虚拟方法,它与模板相互排斥。此外,即使这不是问题,它仍然会遇到与上面#1相同的问题 - 如果在编译时不知道数组大小,那么它也无法在编译时解析模板化函数。
我的实际功能:
virtual void foo(const array<unsigned char, N>& my_array); // but what is N???
总而言之,我是正确的,我唯一真正的选择是使用向量或本机数组,例如,
virtual void foo(const vector<unsigned char> my_array); // unnecessary overhead
virtual void foo(const unsigned char[] my_array, size_t my_array_len); // yuk
或者是否有一些我忽略的技巧会让我使用std :: array或boost :: array?
答案 0 :(得分:4)
在C ++ 11中有std::dynarray
之前,您可以使用std::unique_ptr
:
std::unique_ptr<Foo[]> arr(new Foo[100]);
您可以将其用作arr[0]
,arr[1]
等,并在销毁时调用正确的delete[]
。开销很小(只是指针)。
我认为数组类型唯一指针与std::dynarray
之间的唯一区别是后者具有迭代器和size
其他“容器”属性,并且它将位于“容器”中“部分而不是”一般公用事业“。 [更新:并且编译器可以选择原生支持dynarray
并优化它以使用堆栈存储。]
答案 1 :(得分:1)
如果您在编译时不知道长度,则根本无法使用任何形式的std :: array。
如果您在编译时不知道数组的大小,请认真考虑使用std :: vector。使用可变长度数组(如int foo[n]
)不是标准C ++,如果给定长度足够大,将导致堆栈溢出。此外,你不能编写任何类似数组的包装器(可测量的)比std :: vector更少的开销。
我会用
virtual void foo(const unsigned char* my_array, size_t my_array_len);
并称之为
obj.foo(&vec[0], vec.size());
没有附加的开销,它可以满足您的需求。除了普通数组(int foo[42]
)之外,还可以使用vector和std :: arrays调用此数据,但开销为零。
答案 2 :(得分:0)
其他考虑因素:
所以:
class Foo;
std::array<Foo, 100> aFoo;
构建100个Foo
个对象,(调用Foo::Foo()
100次)
std::vector<Foo> vFoo;
vFoo.reserve(100);
为100个Foo
个对象(在堆上)保留空间,但不构造任何对象。