初始化const成员变量

doo*_*ius 23 c++ initialization-list

我有C++代码,归结为如下所示:

class Foo{
    bool bar;
    bool baz;
    Foo(const void*);
};
Foo::Foo(const void* ptr){
    const struct my_struct* s = complex_method(ptr);
    bar = calculate_bar(s);
    baz = calculate_baz(s);
}
Run Code Online (Sandbox Code Playgroud)

从语义上讲,bar和baz成员变量应该是const,因为它们在初始化后不应该更改.但是,似乎为了使它们如此,我需要在初始化列表中初始化它们而不是分配它们.要清楚,我理解为什么我需要这样做.问题是,我似乎无法找到任何方法将代码转换为初始化列表而不执行以下不良操作之一:

  • complex_method两次电话(对性能不好)
  • 将指针添加到Foo类(会使类大小不必要地变大)

有没有办法让变量const同时避免这些不良情况?

And*_*owl 27

如果您能负担得起C++ 11编译器,请考虑委托构造函数:

class Foo
{
    // ...
    bool const bar;
    bool const baz;
    Foo(void const*);
    // ...
    Foo(my_struct const* s); // Possibly private
};

Foo::Foo(void const* ptr)
    : Foo{complex_method(ptr)}
{
}

// ...

Foo::Foo(my_struct const* s)
    : bar{calculate_bar(s)}
    , baz{calculate_baz(s)}
{
}
Run Code Online (Sandbox Code Playgroud)

作为一般建议,请小心声明您的数据成员const,因为这使您的类无法复制 - 分配和移动 - 分配.如果您的类应该与值语义一起使用,那么这些操作将变得可取.如果情况并非如此,您可以忽略此说明.

  • 紫外线,尤其是最后的音符. (2认同)

eca*_*mur 12

一个选项是C++ 11委托构造函数,如其他答案中所述.与C++ 03兼容的方法是使用子对象:

class Foo{
    struct subobject {
        const bool bar;
        const bool baz;
        subobject(const struct my_struct* s)
            : bar(calculate_bar(s))
            , baz(calculate_baz(s))
        {}
    } subobject;
    Foo(const void*);
};
Foo::Foo(const void* ptr)
    : subobject(complex_method(ptr))
{}
Run Code Online (Sandbox Code Playgroud)

你可以制作barbazconst,或制作subobjectconst,或两者兼而有之.

如果您只subobject常量,那么你就可以计算complex_method并分配给barbaz的构造函数中subobject:

class Foo{
    const struct subobject {
        bool bar;
        bool baz;
        subobject(const void*);
    } subobject;
    Foo(const void*);
};
Foo::Foo(const void* ptr)
    : subobject(ptr)
{}
Foo::subobject::subobject(const void* ptr){
    const struct my_struct* s = complex_method(ptr);
    bar = calculate_bar(s);
    baz = calculate_baz(s);
}
Run Code Online (Sandbox Code Playgroud)

您不能在构造函数体内变异成员的原因const是构造函数体被视为与任何其他成员函数体一样,以保持一致性.请注意,您可以将代码从构造函数移动到成员函数中进行重构,并且分解成员函数不需要任何特殊处理.


Jar*_*d42 8

您可以在C++ 11中使用委托构造函数:

class Foo{
public:
    Foo(const void* ptr) : Foo(complex_method(ptr)) {}

private:
     Foo(const my_struct* s) : bar(calculate_bar(s)), baz(calculate_baz(s)) {}

private:
    const bool bar;
    const bool baz;
};
Run Code Online (Sandbox Code Playgroud)