当前位置: 首页 > 知识库问答 >
问题:

我可以安全地memset一个具有用户定义构造函数的非平凡C结构吗?

曾航
2023-03-14

我知道POD类可以安全地设置。在c 17(?)std::is\U pod被std::is\U标准布局和std::is\U琐碎取代。如果一个非平凡但标准的布局结构只包含char[]数据和一个用户定义的构造函数,那么它可以安全地被memset吗。

具有数十个char[]成员变量的遗留类。

#include <cstring>
#include <memory>
#include <iostream>
#include <type_traits>

struct A
{
    // dozens of fields all char[] which need to initialized to '0'
    char foo[10]; // example char[] field
    // dozens of other fields all char[] which need to be initialized to non '0'

    struct AA
    {
        char bar[10];
        // dozens of other fields
    } sub[7];
};

// What I want to turn struct A into
struct B
{
    B()
    {
        // My question: Is this permissible?
        std::memset(this, '0', sizeof(*this));

        // Initialize all the other member variables that need different values
        std::memset(foo, ' ', sizeof(foo));
    }

    // dozens of fields all char[] which need to initialized to '0'
    char foo[10]; // example char[] field
    // dozens of other fields all char[] which need to be initialized to other values in constructor

    struct BB
    {
        char bar[10];
        // dozens of other fields
    } sub[7];
};

int main(int argc, char* argv[])
{
    bool isTrivialA = std::is_trivial<A>::value;
    bool isStandardLayoutA = std::is_standard_layout<A>::value;
    bool isTrivialCopyA = std::is_trivially_copyable<A>::value;

    std::cout << "Is A trivial: " << isTrivialA << std::endl;
    std::cout << "Is A standard layout: " << isStandardLayoutA << std::endl;;
    std::cout << "Is A trivial copy: " << isTrivialCopyA << std::endl << std::endl;

    bool isTrivialB = std::is_trivial<B>::value;
    bool isStandardLayoutB = std::is_standard_layout<B>::value;
    bool isTrivialCopyB = std::is_trivially_copyable<B>::value;

    std::cout << "Is B trivial: " << isTrivialB << std::endl;
    std::cout << "Is B standard layout: " << isStandardLayoutB << std::endl;
    std::cout << "Is B trivial copy: " << isTrivialCopyB << std::endl;
}

现有代码在使用对象时只对其执行memset。

A legacy;
memset(&legacy, '0', sizeof(legacy));

我想在更新的结构B上调用用户定义的构造函数,因为除了“0”之外,还有几十个字段实际上需要初始化为不同的值。我知道我可以用一个非成员函数来初始化值,但这看起来很笨拙。

B newer; // Call user defined constructor

使用“this”指针的memset()在B中定义的构造函数是否安全/允许?

共有1个答案

颛孙飞鸾
2023-03-14

没有任何机制允许“memset”成为对象上的有效操作。这包括“POD”;标准中从来没有任何内容表明可以直接将数据任意写入POD类型的对象表示中。

简单的可复制使得将对象表示复制到存储中是可以的,并且可以将从该类型的有效实例中获取的此类数据直接复制到该类型的另一个实例中。但即使是这种指定也从未允许将值直接任意设置到对象的表示中。

实际上,只使用(){}值初始化对象更容易,这(如果它没有构造函数,因此符合旧的POD定义)将值初始化成员。

 类似资料:
  • 可以定义一个(a)没有用户定义的构造函数,以及(b)无法生成默认构造函数。例如,下面的: 您仍然可以使用聚合初始化创建Foo的实例: 我的普通编译器(VS2012)将勉强接受这一点,但它提出了两个警告: 警告C4510:'Foo':无法生成默认构造函数。 警告C4610:结构“Foo”永远不能实例化-需要用户定义的构造函数 当然,我刚刚证明了警告#2是错误的——您仍然可以使用聚合初始化来实例化它。

  • 参加以下课程: 由于Foo(std::stringbar_, intbaz_=7);是我唯一的构造函数,编译器不应该为我实现默认构造函数,对吗?我认为我可以构造这个类的唯一两种方法是: 然而,为什么这是可能的? 当唯一的公共构造函数要求其第一个参数具有值时,我不理解如何默认构造类。将默认构造函数设为私有或尝试C 11删除它,没有什么区别。这是怎么发生的 http://ideone.com/CL7I

  • 问题内容: 这是一段代码,作为示例,其余的只是方法(迷宫类的底部)。所以当实例化时,使用 和 这将打印出网格阵列。这是合法的吗?我认为所有类都需要构造函数,它如何打印出二维网格数组? 迷宫课: 问题答案: 不需要 显式 定义构造函数;但是,所有类都必须具有构造函数,如果不提供任何默认构造函数,则将生成默认的空构造函数: 请参见默认构造函数。

  • 如果我有一个简单的结构Foo,定义如下,它是一个POD: 现在想象一下,我想默认初始化成员并直接执行以下操作: 结构不再是吊舱!即使有这样的构造函数: Foo已经失去了它的PODness... 现在,棘手的部分开始了。想象一下,我想添加一个构造函数,取一个: 现在,傅绝对不是一个豆荚。但如果添加默认构造函数: 福现在是一个豆荚! 因此,正如您所看到的,即使我只是想使用第二个示例中的默认值,我也会失

  • 如果我有以下结构 我初始化为 这应该值初始化对象并根据标准执行以下操作: 如果T是一个(可能是cv限定的)类类型,没有用户提供或删除的默认构造函数,则该对象为零初始化,并检查默认初始化的语义约束,如果T有一个非平凡的默认构造函数,则该对象为默认初始化的; 有一个非常重要的构造函数,可以通过以下方法进行检查: 该标准是否意味着我的对象在值初始化的情况下应该始终为零初始化,然后随后默认初始化? 如果我

  • 我的问题是关于OOP(C)中的构造函数。当我在一个类中将默认构造函数定义为private,并且在main中将该类的一个对象初始化为default时,就会出现默认构造函数不可访问的错误。这很好。但我也在Public部分中使用默认参数构造函数,当我再次在main中初始化对象时,就会出现对函数重载的不明确调用。所以我的问题是,如果不能从main访问私有构造函数,那么编译器应该调用公共部分中的构造函数,这