C++11 std::array

12

我想在我的类中使用C++11的std::array作为一个字段。它有两个模板参数(第一个定义数据类型,第二个定义数组的大小)。

但是我只能在构造函数中知道第二个参数。我不熟悉C++11标准,但我猜想在执行过程中无法设置模板参数。

是否有任何替代方法可以替换std::arraystd::vector可能有点过于复杂,因为我永远不会改变它的大小。

4个回答

15

std::vector是最简单易用的;虽然如你所说,如果你永远不需要调整大小,它会浪费一些字节。

std::unique_ptr<T[]>使用new T[size]的结果进行初始化,将是最有效的;它应该与指针的大小相同,并且在销毁时会为您删除分配的内存。但是,它不可复制;如果您想要它可复制,您需要为您的类提供一个复制构造函数。它也不像std::arraystd::vector那样方便,因为它没有标准容器的接口。如果您需要,您可以为其编写STL风格的包装器;但在这种情况下,我只会使用std::vector


3
我建议使用 std::vector 而不是 unique_ptr<T[]>,前者与可以使用迭代器的所有标准库函数兼容。事实上,std::array 的整个设计目的就是为了在普通数组上提供类似的接口。 - Andrew Tomazos
3
的确,使用std::vector更加方便;但是OP确实表达了对效率的担忧,因此也许节省一些字节很重要。 - Mike Seymour
如果你要编写一个类似STL的包装器,那么它至少也需要知道自己的大小。你不能只忽略容量。 - UncleBens

11

我不熟悉C++11标准,但我认为在执行期间设置模板参数是不可能的。

无法将仅在运行时已知的值作为模板参数传递...由模板实例化创建的代码必须在编译时创建,因此它不能依赖于运行时值。

一些可能的解决方案是为一些常见的数组大小值创建模板特化,然后为可能的最大大小值。 我认为这将是一种相当低效的工作方式。

老实说,在您的情况下,std::vector 很可能是最好的解决方案,因为您可以通过动态分配在运行时调用 resize() 来使其成为正确的大小。


1
使用std::vector (size_t n)构造函数,而不是resize() - Sebastian Mach
2
如果您的所有项目不相同,则可以使用@phresnel:或reserve +一系列push_back/emplace_back - Matthieu M.

6

std::array是在编译时就知道大小的静态数组。如果你直到运行时才知道大小,请使用std::vector。如果您不要调整大小,则几乎没有开销。

class Container
{
    vector<T> v;
    Container(int i) : v(i) { v.shrink_to_fit(); }
};

如果您担心空间问题:
请参考链接http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit
不确定是否有一种方法可以构造已经修剪过的向量。标准似乎没有要求构造时进行修剪,尽管在实践中许多实现都会这样做。
此外,您还可以使用vector(size_t N,T t)构造一个向量,该向量将将每个初始元素设置为t(否则元素将被默认构造)。

如果我没记错的话,向量是根据你所要求的确切容量构建的。之后无需缩小。缩小向量的复制和交换技巧也依赖于此。 - Xeo
1
有趣的是,对于某些基准测试,根本没有任何开销,而且使用std::vector的代码产生的向量化SSE代码与本机数组相同(至少在g++中)。 - Sebastian Mach
我认为数组是在固定位置分配的,而向量是动态分配的。 - Andrew Tomazos
原则上:是的。实际上:优化器可能会根据情况放弃动态分配。 - Sebastian Mach
@phresnel:我的意思是,上面的sizeof(Container)将是恒定的,而如果我使用了一个数组,sizeof(Container)将与数组大小成比例。我不确定优化器是否能够处理这个问题,因为它在编译时不知道它是否会被从尚未链接的其他编译单元调整大小。 - Andrew Tomazos
@user1131467:在跨编译单元的情况下,除非您拥有非常好的LTO,否则这将更加困难。通常,除了NRVO / RVO之外,优化器可能不会改变整个程序的可观察行为。但是经常会出现这种情况,即容器被私有存储,最好通过pimpl惯用语法。然后,编译器将独立处理向量代码而不考虑其他单元,并可能应用此类优化。 - Sebastian Mach

3

如果你在运行时不知道数组的大小,那么你需要使用std::vector。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接