繁体   English   中英

构造函数初始化列表与构造函数主体

[英]Constructor Initializer List vs Constructor Body

假设someString初始化有点复杂,因此我们编写了一个简单的成员 function stringInitialization()用于在构造函数的主体中初始化someString

class DemoL {
private:

    int someNumber;
    std::string someString;

    void stringInitialization() {
        if (someNumber == 1) {
            someString = "FIRSTSTRING";
        } else if (someNumber == 2) {
            someString = "SECONDSTRING";
        } else {
            someString = "";
        }
    }

public:
    explicit DemoL(int rNumber) :
            someNumber(rNumber) {
        stringInitialization();
    }
};

这样,我假设someString将在构造函数的主体之前默认初始化,只有在此之后才会通过调用stringInitialization()对其进行修改。

所以,让我们稍微修改一下代码,以便我们在构造函数初始化列表中初始化someString

class DemoL {
private:

    int someNumber;
    std::string someString;

    std::string stringInitialization() const {
        if (someNumber == 1) {
            return "FIRSTSTRING";
        } else if (someNumber == 2) {
            return "SECONDSTRING";
        } else {
            return "";
        }
    }

public:
    explicit DemoL(int rNumber) :
            someNumber(rNumber),
            someString(stringInitialization()) {}
};

您能否告诉我第二种变体是否更有效和正确?

你的假设是正确的。 构造函数DemoL(int rNumber)需要能够默认构造成员someString ,这没有问题,因为std::string是默认可构造的。

显而易见的一点是,一个成员可能不是默认可构造的,在这种情况下,您必须对其进行初始化。

但即使是这样,如果您在之后立即更改它,默认构造它可能会浪费资源,所以第二种选择对我来说似乎更好,因为它直截了当。

但是,由于stringInitialization按值返回,我会使用std::move ,不,这实际上是一个坏主意,正如评论中指出的那样。

所以作为一个结论:

  • 这两个代码对于someNumber是相同的
  • 第一个代码默认初始化someString (“调用” std::basic_string<...>::basic_string )然后分配它(调用std::basic_string<...>::operator=
  • 当对stringInitialization的调用返回(调用basic_string<...>::basic_string(const char*) )时,第二个代码从字符串文字构造返回的std::string值,然后复制构造someString (调用basic_string<...>::basic_string(basic_string&&) ); 实际上发生复制省略是因为stringInitialization返回一个右值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM