shi*_*jin 33 c++ memcpy reinterpret-cast c++11
是底层位表示一个std::array<T,N> v和T u[N]一样的吗?
换句话说,将N*sizeof(T)字节从一个复制到另一个是否安全?(通过reinterpret_cast或memcpy.)
编辑:
为了澄清,重点是相同的位表示和reinterpret_cast.
例如,假设我将这两个类放在一些简单的可复制类型上T,对于某些类N:
struct VecNew {
std::array<T,N> v;
};
struct VecOld {
T v[N];
};
Run Code Online (Sandbox Code Playgroud)
还有遗留功能
T foo(const VecOld& x);
Run Code Online (Sandbox Code Playgroud)
如果表示相同,则此调用是安全的并且避免复制:
VecNew x;
foo(reinterpret_cast<const VecOld&>(x));
Run Code Online (Sandbox Code Playgroud)
Bar*_*rry 20
这并不直接回答您的问题,但您应该只使用std::copy:
T c[N];
std::array<T, N> cpp;
// from C to C++
std::copy(std::begin(c), std::end(c), std::begin(cpp));
// from C++ to C
std::copy(std::begin(cpp), std::end(cpp), std::begin(c));
Run Code Online (Sandbox Code Playgroud)
如果T是一个简单的可复制类型,这将编译为memcpy.如果不是,那么这将做元素方面的复制分配并且是正确的.无论哪种方式,这都是正确的事情并且非常易读.无需手动字节算术.
Sla*_*ica 13
std::array提供方法data(),可用于复制到适当大小的c风格数组:
const size_t size = 123;
int carray[size];
std::array<int,size> array;
memcpy( carray, array.data(), sizeof(int) * size );
memcpy( array.data(), carray, sizeof(int) * size );
Run Code Online (Sandbox Code Playgroud)
此容器是一种聚合类型,其语义与包含C样式数组T [N]作为其唯一非静态数据成员的结构相同.
所以内存占用似乎与c风格的数组兼容,但是reinterpret_cast当你有一个没有任何开销的正确方法时,你不清楚为什么要使用"hacks" .
该data()方法的要求是它返回一个指针T*,使得:
[data(), data() + size())是一个有效的范围,和data() == addressof(front()).
这意味着您可以通过data()指针顺序访问每个元素,因此,如果T可以轻松地复制,您确实可以使用从数组memcpy复制sizeof(T) * size()字节T[size()],因为这相当于memcpy单独使用每个元素.
但是,你不能使用reinterpret_cast,因为这会违反严格的别名,因为data()不需要实际上由数组支持 - 而且,即使你要保证std::array包含一个数组,因为C++ 17你不能(甚至使用reinterpret_cast)将指向数组的指针转换为指向其第一个成员的指针(您必须使用std::launder).
我说是(但标准并不能保证).
根据[array]/2:
数组是一个聚合([ dcl.init.aggr ]),可以使用最多N个元素进行列表初始化,这些元素的类型可以转换为T.
并[dcl.init.aggr]:
的聚集体是一个数组或一个类(第[类])与
没有用户提供的,显式的或继承的构造函数([class.ctor]),
没有私有或受保护的非静态数据成员(Clause [class.access]),
没有虚函数([class.virtual]),和
没有虚拟,私有或受保护的基类([class.mi]).
鉴于此,只有在课程开头没有其他成员且没有vtable时,才能进行"可以列表初始化".
然后,data()指定为:
constexpr T* data() noexcept;
返回:指针,这[data(), data() + size())是一个有效的范围,和data() == addressof(front()).
该标准基本上想要说"它返回一个数组",但为其他实现留下了空间.
唯一可能的其他实现是具有单个元素的结构,在这种情况下,您可能会遇到别名问题.但在我看来,这种方法除了复杂性之外不会增加任何东西.将数组展开到结构中没有任何好处.
因此,不作为数组实现是没有意义 的.std::array
但确实存在漏洞.
array 对实例化它的基础类型没有太多要求.
要使用或执行复制有任何可能的结果,您实例化它的类型必须是可以轻易复制的.将这些项存储在一个中不会影响(和这样的)仅适用于普通可复制类型的要求.memcpyreinterpret_castarraymemcpy
array需要是一个连续的容器和一个聚合,这几乎意味着元素的存储必须是一个数组.标准显示为:
T elems[N]; // exposition only
Run Code Online (Sandbox Code Playgroud)
然而,它后来有一个注释,至少暗示它是一个数组是必需的(§[array.overview]/4):
[注意:成员变量
elems仅用于展示,以强调这array是一个类聚合. 该名称elems不是数组接口的一部分. - 尾注]
[强调补充]
请注意它实际上只是elems不需要的特定名称.