c++ - 构造函数初始化列表与构造函数主体
问题描述
假设someString初始化有点复杂,因此我们编写了一个简单的成员函数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=
) - 第二个代码在调用返回(调用)
std::string
时从字符串文字构造返回值,然后复制构造(调用);实际上发生复制省略是因为返回一个右值。stringInitialization
basic_string<...>::basic_string(const char*)
someString
basic_string<...>::basic_string(basic_string&&)
stringInitialization
推荐阅读
- sql - 插入到不同的表中
- html - 阻止悬停在内部元素上?
- java - 了解 getViewTreeObserver
- java - 使用递归查找特定字符的出现次数
- apache-kafka - 卡夫卡消费者滞后的锯齿模式是如何出现的?
- excel - Excel 公式 - 如果这样,那么 - 在一个范围内平均
- ios - 向标签添加手势?
- python - 微调预训练 tensorflow api (SSD mobilenet) 的最佳方法
- java - 从 Java 向 Google Assistant 发送请求
- accordion - Div 未在 Angular 6 中的特定 ngFor 下方打开