在构造函数代码之前禁用默认的类成员初始化

时间:2018-12-28 18:15:24

标签: c++ default-constructor member-initialization

在C ++中,在包含类的构造函数执行之前,默认情况下构造在成员初始化列表中构造为 not 的类的任何成员。但是,如果该成员变量无论如何在其所在类的构造函数内构造,都显得非常浪费。

我在下面提供了一个示例来阐明我的意思。这里,Example类具有类型为x的成员变量LargeIntimidatingClass。使用成员初始化列表(Example中的第一个构造函数)x仅构造一次。但是,如果无法使用成员初始化列表合理构造x,它将被构造两次!

//This class used as part of the example class further below
class LargeIntimidatingClass {
    // ...
    //many member variables and functions
    // ...

    LargeIntimidatingClass() {
        //Painfully expensive default initializer
    }

    LargeIntimidatingClass(int a, double b) {
        //Complicated calculations involving a and b
    }
};

//Here, this class has a LargeIntimidatingClass as a member variable.
class Example {
    LargeIntimidatingClass x;
    char c;

    //Basic member initialization list constructor. Efficient!
    Example(int a, double b, char c) : x(a,b), c(c) {}

    //What if the parameters to the LargeIntimidatingClass's constructor
    //need to be computed inside the Example's constructor beforehand?
    Example(std::string sophisticatedArgument) {
        //Oh no! x has already been default initialized (unnecessarily!)

        int a = something1(sophisticatedArgument);
        double b = something2(sophisticatedArgument);
        //x gets constructed again! Previous (default) x is totally wasted!
        x = LargeIntimidatingClass(a,b);

        c = something3(sophisticatedArgument);
    }
};

是的,我意识到在这个愚蠢的示例中,您可以编写Example(string s) : x(f1(s),f2(s)), c(f3(s)) {},但是我敢肯定,您可以想象这样一种情况:将一堆逻辑推入成员初始化列表很麻烦(甚至是不可能的)。

在成员初始化列表中未列出成员变量时,是否可以禁用其默认构造函数?

3 个答案:

答案 0 :(得分:2)

禁用语言工作方式的组成部分?不会。但是您可以重构以使用 语言,也可以通过多种方式解决它。

  1. 具有指向扩展类的(智能)指针成员。
  2. 将成员设为std:aligned_storage并通过放置new来创建对象。然后自己仔细管理对象的寿命。
  3. 按住std:optional。管理初始化,并让库类型管理其余的对象,从而节省一些对象大小。

答案 1 :(得分:2)

您不能禁用该构造。在到达构造函数的主体之前,必须初始化所有类成员。也就是说,您可以轻松解决此问题。您可以添加一个私有静态成员函数,该函数获取ab并从中返回LargeIntimidatingClass

class Example {
    LargeIntimidatingClass x;
    char c;
    static LargeIntimidatingClass make_LargeIntimidatingClass(std::string sophisticatedArgument)
    {
        int a = something1(sophisticatedArgument);
        double b = something2(sophisticatedArgument);
        return LargeIntimidatingClass(a,b);
    }
    static char make_c(std::string sophisticatedArgument)
    {
        return something3(sophisticatedArgument);
    }
public:

    //Basic member initialization list constructor. Efficient!
    Example(int a, double b, char c) : x(a,b), c(c) {}

    // now we use helpers to initialize in the member initialization list
    Example(std::string sophisticatedArgument) : x(make_LargeIntimidatingClass(sophisticatedArgument), c(make_c(sophisticatedArgument) {
        //now everything is initialized correctly
    }
};

答案 2 :(得分:1)

  

在成员初始化列表中未列出成员变量时,是否可以禁用其默认构造函数?

不,那不可能。