什么特质/概念可以保证memsetting一个对象是明确定义的?

YSC*_*YSC 20 c++ metaprogramming sfinae c++14 c++20

假设我已经定义了一个zero_initialize()函数:

template<class T>
T zero_initialize()
{
    T result;
    std::memset(&result, 0, sizeof(result));
    return result;
}

// usage: auto data = zero_initialize<Data>();
Run Code Online (Sandbox Code Playgroud)

调用zero_initialize()某些类型会导致不确定的行为1,2.我目前正在执行T验证std::is_pod.由于这个特性在C++ 20中被弃用以及概念的出现,我很好奇zero_initialize()应该如何发展.

  1. 什么(最小)特征/概念可以保证memsetting一个对象是明确定义的?
  2. 我应该用std::uninitialized_fill而不是std::memset吗?为什么?
  3. 对于类型子集,此函数是否已被C++初始化语法之一淘汰?或者它将与即将到来的未来C++版本一起使用?

1) 删除班级的所有成员.
2) 在库类(std :: string)上使用memset时,"未定义的行为"是什么原因?[关闭]

Nic*_*las 23

在C++中技术上没有对象属性,它指定用户代码在法律上可以memset是C++对象.这包括POD,所以如果你想成为技术人员,你的代码永远不会正确.甚至TriviallyCopyable也是关于在现有对象之间进行逐字节复制的属性(有时通过中间字节缓冲区); 它没有说明发明数据并将其推入对象的位.

话虽这么说,你可以合理地肯定,如果你测试is_trivially_copyable 这将是有效的is_trivially_default_constructible.最后一个很重要,因为一些TriviallyCopyable类型仍然希望能够控制它们的内容.例如,这样的类型可以有一个int始终为5 的私有变量,在其默认构造函数中初始化.只要没有访问变量的代码改变它,它就会一直是5.C++对象模型保证了这一点.

所以你不能memset这样的对象,仍然可以从对象模型中获得明确定义的行为.

  • 我很欣赏双重答案(语言 - 律师/现实生活存在). (5认同)

Nat*_*ica 8

什么(最小)特征/概念可以保证memsetting一个对象是明确定义的?

根据std::memsetcppreference引用,memsetTriviallyCopyable类型的行为是未定义的.因此,如果可以memset使用TriviallyCopyable,那么您可以static_assert在类中添加一个来检查它

template<class T>
T zero_initialize()
{
    static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
    T result;
    std::memset(&result, 0, sizeof(result));
    return result;
}
Run Code Online (Sandbox Code Playgroud)

这里我们std::is_trivial_v用来确保不仅类很容易复制,而且它还有一个简单的默认构造函数,所以我们知道初始化为零是安全的.

我应该用std::uninitialized_fill而不是std::memset吗?为什么?

您不需要在此处,因为您只是初始化单个对象.

对于类型子集,此函数是否已被C++初始化语法之一淘汰?或者它将与即将到来的未来C++版本一起使用?

值或支撑初始化确实使此函数"过时". T()并且T{}会给你一个初始化的值T,如果T没有默认的构造函数,它将被初始化为零.这意味着你可以将函数重写为

template<class T>
T zero_initialize()
{
    static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
    return {};
}
Run Code Online (Sandbox Code Playgroud)

  • 应该注意的是,TriviallyCopyable只保证byte*replication*有效.如我所知,通过字节数组设置类型的值是不允许的.此外,TriviallyCopyable*不*保证默认可构造.所以不允许你的`zero_initialize`函数.它只会在您验证`trivially_default_constructible`时才有效. (2认同)