我有一个const float *指向一个巨大的数组,并希望能够通过std :: array访问这些元素。 做这个的最好方式是什么?如果可能的话,不要复制元素。
谢谢!
答案 0 :(得分:3)
为了使用std::array
,您需要在编译时知道数组的大小。您创建一个空数组并使用std::copy
将元素复制到数组中。
如果使用const float*
的代码仅在运行时知道该大小,则您无法使用std::array
但必须使用std::vector
。 std::vector
有一个构造函数,您可以将指针传递给范围的开头和结尾以复制到其中。
请注意,在这两种情况下,容器都拥有原始元素的副本。
如果可能的话,不要复制元素。
不,那是不可能的。 C ++标准容器旨在拥有其内容,而不仅仅是表示它们的视图。
这是一个说明差异的例子:
#define SIZE 10 // let's assume some C or legacy code which uses macros
// ...
void f(const float* arr)
{
// size is known at compile time
std::array<float, SIZE> a;
std::copy(arr, arr + SIZE, begin(a));
}
void g(const float* arr, int size)
{
// size is only known at runtime
std::vector<float> v(arr, arr + size);
}
答案 1 :(得分:2)
标准库中至少有两个建议添加类似的东西。一个是std::experimental::to_array<T,N>()
,它可以生成整个数据的深层副本。这在时间和内存方面都是浪费,但如果你真的想创建一个副本,尤其是你无法创建然后修改的const
副本,那么它可能会很有用。
如果你想要的是一个由任意指针和元素数表示的数据范围的容器接口,Guideline Support Library提供了一个span
模板。我建议,如果你同时传递它们,你将它们包装在一个类似于此的轻量级对象中。
既然你说你可以改变构造函数的接口,我强烈建议你这样做。如果要保留采用std::array
的版本,可以将其委托给采用任意数据范围的版本,例如:
#include <algorithm>
#include <array>
#include <iterator>
#include "span"
MyClass::MyClass( const span<value_type>& s /*, more, params */ )
{
/* In this example, m_storage is some private container and span has a
* container interface.
*/
auto it = std::back_inserter(m_storage);
std::copy_n( s.begin(), s.size(), it );
// ...
}
MyClass::MyClass( std::array<value_type, initializer_size>& a /*, more, params */ )
: MyClass( span<value_type>( a.data(), a.size() ) /*, more, params */ )
{}
答案 2 :(得分:0)
std :: array不接受指针的所有权。你必须复制元素。使用std :: copy。它适用于抽象迭代器,指针也符合条件。
const float *source = ...; // C array of at least of size N
std::array<float, N> destination;
std::copy(source, source + N, destination.begin());
抛开:不复制元素,支持获取指针所有权的任何容器的元素类型也必须是const float。或者你必须使用const_cast&lt;&gt;如果你确定指针实际上不是const float。请只使用const_cast&lt;&gt;如果由于外部API的缺陷而绝对不可避免的情况虽然:)