c++ - 我的同事喜欢使用memset初始化struct,我怎样才能说服他不要这样做?

标签 c++ memory-management initialization

我的同事喜欢编写代码来使用 memset 初始化结构体的字段,如下所示:

struct Fun {
    int mem;
    int cpu;
    std::map<int, int> cpumap;
    std::string str;

    Fun() {
       int size = (char*)&(this->cpumap) - (char*)this;
       memset(this, 0, size);
    }
};

他说这段代码 100% 正确并且可以很好地完成工作。那么这是 C++ 中初始化结构体的典型方法吗?我的意思是这种代码的行为定义得很好?

最佳答案

memset , malloc , calloc等等都是 C 的做事方式 - 它们不是 C++-idomatic,并且仅在 C++ 中真正受支持,因此您可以直接使用 C 代码。请注意,即使在 C 中,您也可以使用 struct someStruct = {0}语法对结构进行零初始化,因此使用 memset即使在 C 中,使用结构也是不必要的。memset实际上是用于将缓冲区清零,而不是对象。

至于他关于正确性的断言,我会说他实际上是错误的。

以下是我的观察结果的详细 list :

  • 需要程序员手动将表达式中的第一个和最后一个成员放入计算size (为什么不直接使用 sizeof 运算符?)。
    • 我注意到您给出的示例的意图并不明确:虽然它清除了三个标量成员,但它是否也意味着清除 memcpumap成员? (如果另一个程序员添加了这两个字段并忘记更新构造函数怎么办?)
  • 在继承的情况下失败:this的值将指向最顶层父级的开始,而不是第一个非继承字段,因此除了盲目覆盖父级数据之外,如果父级构造函数具有相同的“初始化”逻辑,您还会多次执行此操作。
  • size计算发生在运行时,而不是编译时,这会浪费 CPU 周期。
  • 他正在使用int size而不是size_t size因此它可能不适用于 sizeof(void*) != sizeof(int) 的系统(例如 x64、一些晦涩的 ISA、某些嵌入式架构等)
  • 他盲目地转换到 (char*)即使这可能不合适。而sizeof(char)保证为 1我不相信char*有保证始终成为void*的合适代理。
    • 这也是 C 风格的 Actor 阵容。在 C++ 中,强制转换运算符 static_cast , reinterpret_cast ,和dynamic_cast总是优先于 (T) -风格转换。
  • 它假设所有成员都存在于其声明顺序定义的范围内。您不能在 C++ 中做出此假设(请参见此处: Do class/struct members always get created in memory in the order they were declared? ),因为 1998 和 2003 规范指出:

    The order of allocation of nonstatic data members separated by an access-specifier is unspecified

    因此,在这种情况下,他的代码将依赖于未定义的行为:

    struct Foo {
    private:
        int a;
        int b;
    public:
        int c;
    private:
        int d;
    }
    Foo::Foo() {
        int size = (char*)&this.d - (char*)&this.a;
    }
    
  • 危险的是,您不能假设归零成员是“有效的” - std::map 的实现和std::string可能有不能为零的内部成员,通过盲目删除它们,您会将它们置于未知状态。这很危险。

要点是:不要这样做。

C++ 方式是使用初始化列表,它提供了很多编译时安全性和保证,并且需要一个保证类型安全的显式初始值。语法为:

struct Foo {
    someType x;
    int y;
    foo bar;
};

Foo:Foo() :
    x(0),
    y(0),
    bar(some_initial_bar_value) {
    // any sequential init logic goes here
}

关于c++ - 我的同事喜欢使用memset初始化struct,我怎样才能说服他不要这样做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36243747/

相关文章:

python - 创建一个独特的虚拟对象

c++ - `string s("hello") ;` and ` string s = "hello";` 有区别吗

c++ - 使用 RegQueryInfoKey

c++ - 寻找 std::cin 的结尾返回 -1 错误和错误位

c++ - 为什么 C++ STL 中的算法、迭代器和容器是分离的

c++ - std::map - C++ 需要所有声明的类型说明符

iphone - 从 SearchBar 查询执行 NSRange 后抛出的异常

c - 为什么指针数组的 free() 不释放内存?

objective-c - 圆弧 : __bridge versus __bridge_retained using contextInfo test case

c++ - 使用函数调用初始化字符串成员 c++