memset 和 std::complex<double> 的动态数组
memset and a dynamic array of std::complex<double>
因为 std::complex 是一个非常重要的类型,使用 GCC 8.1.1 编译以下内容
complex<double>* z = new complex<double>[6];
memset(z,0,6*sizeof*z);
delete [] (z);`
产生警告
clearing an object of non-trivial type
我的问题是,这样做真的有任何潜在的危害吗?
从不,从不,从不 memset
非 POD 类型。他们有构造函数 是有原因的 。仅仅在它们上面写一堆字节是极不可能给出期望的结果的(如果是这样,类型本身设计得很糟糕,因为它们显然应该首先是 POD - 或者你只是不走运未定义的行为 似乎在 这种 情况下工作 - 在更改优化级别、编译器或平台(或 moon)相)).
只是不要这样做。
std::memset
is only defined if the pointer it is modifying is a pointer to a TriviallyCopyable type. std::complex
的行为保证是 LiteralType,但据我所知,它不能保证是 TriviallyCopyable,意思是std::memset(z, 0, ...)
不可移植
就是说,std::complex
有一个 array-compatibility guarantee,它表示 std::complex<T>
的存储恰好是两个连续的 T
,并且可以这样重新解释。这似乎表明 std::memset
实际上很好,因为它将通过这种面向数组的访问进行访问。这也可能意味着 std::complex<double>
是 TriviallyCopyable,但我无法确定。
如果您想这样做,我建议您安全起见,static_assert
认为 std::complex<double>
是 TriviallyCopyable:
static_assert(std::is_trivially_copyable<std::complex<double>>::value);
如果该断言成立,那么可以保证 memset
是安全的。
无论哪种情况,使用 std::fill
:
都是安全的
std::fill(z, z + 6, std::complex<double>{});
它 optimizes down 调用 memset
,尽管在它之前还有一些指令。我建议使用 std::fill
,除非您的基准测试和分析表明那几条额外的指令导致了问题。
这个问题的答案是,对于符合标准的 std::complex
,new
之后不需要 memset
。
new complex<double>[6]
会将复数初始化为 (0, 0)
因为它调用默认(非平凡)构造函数初始化为零。
(不幸的是,我认为这是一个错误。)
https://en.cppreference.com/w/cpp/numeric/complex/complex
如果发布的代码只是 new
和 memset
之间缺少代码的示例,那么 std::fill
会做正确的事情。
(部分原因是特定的标准库实现在内部知道 std::complex
是如何实现的。)
因为 std::complex 是一个非常重要的类型,使用 GCC 8.1.1 编译以下内容
complex<double>* z = new complex<double>[6];
memset(z,0,6*sizeof*z);
delete [] (z);`
产生警告
clearing an object of non-trivial type
我的问题是,这样做真的有任何潜在的危害吗?
从不,从不,从不 memset
非 POD 类型。他们有构造函数 是有原因的 。仅仅在它们上面写一堆字节是极不可能给出期望的结果的(如果是这样,类型本身设计得很糟糕,因为它们显然应该首先是 POD - 或者你只是不走运未定义的行为 似乎在 这种 情况下工作 - 在更改优化级别、编译器或平台(或 moon)相)).
只是不要这样做。
std::memset
is only defined if the pointer it is modifying is a pointer to a TriviallyCopyable type. std::complex
的行为保证是 LiteralType,但据我所知,它不能保证是 TriviallyCopyable,意思是std::memset(z, 0, ...)
不可移植
就是说,std::complex
有一个 array-compatibility guarantee,它表示 std::complex<T>
的存储恰好是两个连续的 T
,并且可以这样重新解释。这似乎表明 std::memset
实际上很好,因为它将通过这种面向数组的访问进行访问。这也可能意味着 std::complex<double>
是 TriviallyCopyable,但我无法确定。
如果您想这样做,我建议您安全起见,static_assert
认为 std::complex<double>
是 TriviallyCopyable:
static_assert(std::is_trivially_copyable<std::complex<double>>::value);
如果该断言成立,那么可以保证 memset
是安全的。
无论哪种情况,使用 std::fill
:
std::fill(z, z + 6, std::complex<double>{});
它 optimizes down 调用 memset
,尽管在它之前还有一些指令。我建议使用 std::fill
,除非您的基准测试和分析表明那几条额外的指令导致了问题。
这个问题的答案是,对于符合标准的 std::complex
,new
之后不需要 memset
。
new complex<double>[6]
会将复数初始化为 (0, 0)
因为它调用默认(非平凡)构造函数初始化为零。
(不幸的是,我认为这是一个错误。)
https://en.cppreference.com/w/cpp/numeric/complex/complex
如果发布的代码只是 new
和 memset
之间缺少代码的示例,那么 std::fill
会做正确的事情。
(部分原因是特定的标准库实现在内部知道 std::complex
是如何实现的。)