1

因此 std::array 和 boost::array (它们几乎相同,我在下文中将模糊地称为“数组”)旨在为数组提供一个容器对象,该对象不会产生不必要的向量开销,如果数组不会动态改变大小。但是,它们都是通过将数组大小不作为构造函数参数而是模板参数来设计的。结果:vector 允许在对象创建后动态调整大小;数组需要在编译时知道大小。

据我所见,如果您有一个数组,您将在创建对象时知道其大小,但在编译时不知道,那么您唯一的选择是 1)使用向量会产生不必要的额外开销,2)使用(非容器类型)本地数组(例如int foo[42];),或 3)从头开始编写您自己的数组包装类。那么这是正确的吗,这是一种介于两者之间的情况,您可能想使用数组而不是向量,但不能?或者有什么我可以做的魔法可以让数组对我有用吗?

这是启发这个问题的一些细节(好的,很多),以防它帮助您理解:

我有一个模块 - 比如说调用者 - 它将在运行时重复生成二进制数据(无符号字符 [] 或数组),然后将其传递给另一个模块 - 比如说被调用者。被调用者模块不会修改数组(它会复制并在必要时进行修改),所以一旦调用者模块最初创建了数组,它就不会改变大小(也不会改变内容)。但是,会出现两个问题:1)调用者可能不会在每次生成数组时都生成相同大小的数组——它会在创建数组时在 rutime 知道数组大小,但在编译时不知道。2)调用者将数组传递给被调用者的方法需要能够获取调用者传递给它的任何大小的数组。

我考虑过使它成为一个模板函数,例如,

template<size_t N> void foo(const array<unsigned char, N>& my_array);

但是,我使用接口类将接口与被调用模块中的实现分开。因此,该函数必须是一个虚方法,它与被模板化是互斥的。此外,即使这不是问题,它仍然存在与上面的#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?

4

3 回答 3

4

在我们使用std::dynarrayC++11 之前,您可以使用std::unique_ptr

std::unique_ptr<Foo[]> arr(new Foo[100]);

您可以将其用作arr[0],arr[1]等,它会delete[]在销毁时调用正确的。开销很小(只是指针)。

我认为数组类型的唯一指针之间的唯一区别std::dynarray是后者具有迭代器和size其他“容器”属性,并且它将位于“容器”部分而不是“通用实用程序”中。[更新:编译器可以选择本地支持dynarray和优化它以使用堆栈存储。]

于 2013-07-09T23:43:06.090 回答
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]) 之外,它还可以用向量和 std::arrays 调用,开销为零。

于 2013-07-10T00:03:35.990 回答
0

其他注意事项:

  • 数组在堆栈上分配。这比在堆上分配快得多。
  • 数组在创建时总是初始化它们的所有元素。

所以:

    class Foo;
    std::array<Foo, 100> aFoo;

构造 100 个Foo对象,(调用Foo::Foo()100 次)同时

    std::vector<Foo> vFoo;
    vFoo.reserve(100);

为 100 个对象(在堆上)保留空间Foo,但不构造任何对象。

于 2013-07-10T00:44:24.050 回答