假设我有一个班级Foo
:
class Foo {
public:
Foo(std::string s) noexcept : bar(std::move(s)) {}
// version 1
Foo(int x) noexcept
{
// do something...
std::string s = // ...to get a string from `x`
*this = Foo(std::move(s));
}
// version 2
Foo(int x) noexcept
: Foo([x] {
// do something...
std::string s = // ...to get a string from `x`
return Foo(std::move(s));
}())
{}
private:
std::string bar;
};
版本1具有更清晰的代码,但有两个缺点:1)如果成员的默认初始化很昂贵,或者如果有const成员,则此版本将不起作用; 2)在构造函数安全中分配给*this
吗?我有这个问题,因为我担心在构造函数返回之前对象可能处于某种“不完整”状态。
答案 0 :(得分:3)
是的,你可以这样做。当构造函数体开始运行时,所有字段都已初始化,并且对象有效分配给。 (假设你的赋值运算符不依赖于后面在构造函数体中建立的任何前置条件。)
答案 1 :(得分:2)
保持简单:
Foo(int x) noexcept : Foo(getString(x)) { }
private:
std::string getString(int x) { // make it static if possible
// do something...
return // ...get a string from `x`
}
答案 2 :(得分:1)
*this = Foo(std::move(s));
表示operator=( Foo(std::move(s)) );
,您可以从构造函数中调用函数。
我看到的唯一问题是所有这个字符串结构都可能抛出一个内存不足的异常,这会终止程序。虽然可能会考虑如果将来开发的课程更复杂,可能会出现问题。
一个小问题是此代码将bar
初始化为空字符串然后分配字符串。最好使用您希望字符串保存的值初始化bar
,例如:
Foo(int x) noexcept: bar( calculate_string(x) ) {}
您可以在其中编写一个函数calculate_string
,返回bar
的值。