【发布时间】:2016-11-20 01:32:21
【问题描述】:
另一个 C++ 问题,我试图弄清楚在构造对象时使用“=”有什么影响。考虑:
class Foo {
private:
int bar;
int baz;
public:
Foo(int bar, int baz)
:bar(bar), baz(baz) {}
};
int main() {
Foo foo1{4, 2};
Foo foo2 = {4, 2};
Foo foo3 = Foo{4, 2}; // I prefer this one for aesthetic reasons.
return 0;
}
有什么区别?我应该坚持哪一个作为最佳做法?
此外,当我们讨论最佳实践的主题时,我听说将 explicit 添加到构造函数是一个好主意™,因为隐式转换的奇怪行为。所以我在Foo的构造函数中添加了explicit:
public:
explicit Foo(int bar, int baz)
:bar(bar), baz(baz) {}
突然,这个:
Foo foo2 = {4, 2};
编译失败,报错:
error: chosen constructor is explicit in copy-initialization
这是为什么呢?
【问题讨论】:
-
重要的两个区别: 1) 如您所见,复制初始化不适用于显式构造函数。 2)
auto在复制和直接初始化之间推导std::initializer_list的方式不同。其余的,它在 C++17 中变得没有意义。 -
Foo foo3 = Foo{4, 2}; // I prefer this one.我不知道为什么。从概念上讲,它涉及一个完全没有意义的额外副本,尽管实际上一个好的优化编译器会消除你的错误。但它只是看起来冗长而丑陋。当它是多余的时候,为什么要写得比你必须写的多?Foo foo{4, 2};更胜一筹。 -
“我听说向构造函数添加显式...” - 除了是一个可怕的笼统陈述之外,您听到的任何地方的未提及作者是否提到 为什么 他们认为这是一个好主意?你同意,不同意,还是根本不理解这个理由?最后,this description of
explicit值得回顾。 -
另请注意,
auto将始终推断出std::initializer_list的上述规则被视为缺陷并在 C++17 中修复 - 其中auto thing = {a, b}具有 2+ 个元素仍将推断出std::initializer_list但是 例如auto str{ std::to_string(num) };现在将正确地 IMO 推断要构造的类型。这样做的非常正确的理由是它避免了我们必须记住两组规则 - 从而使统一初始化,嗯,统一。值得注意的是g++已经将其向后移植到旧标准,但 Clang 没有(可以说更有礼貌!) -
@underscore_d “我不知道为什么”,美学。我不知道这就是为什么我要问的陈述之间的区别。
标签: c++ c++11 constructor initialization initializer-list