这是受到Andrei Alexandrescu的post的启发。
使用以下方法初始化表达式的专家和概念是什么?我什么时候应该更喜欢一个?
auto v = expr;
T v = expr;
auto v(expr);
T v(expr);
auto v { expr };
T v {expr};
答案 0 :(得分:15)
auto v = expr;
auto v(expr);
在您的代码中,您不知道expr
的类型并希望保持通用,或者在您的代码中,绝对清楚expr
的类型(在上面的行中定义)等等),auto
不会增加混淆。
初始化的形式,parens与否,是无关紧要的(仅与语言律师有关,因为存在微妙的差异)。使用你感觉更舒服的东西。
T v = expr;
T v(expr);
如果您的代码中不清楚expr
是什么(定义太远,等等......),或者您不知道expr
的类型但想要{{1} }属于v
类型。如果你想继续使用“expr”所具有的“种类值”(即T
是字符串而expr
是字符串类型),请使用第一种形式。如果您构建了一种全新的值(即T
,并且Widget
是窗口小部件的颜色),请使用第二种形式。
expr
永远不要在当前的C ++中使用它(可能在未来几年内)。它会将auto v { expr };
声明为v
。如果需要,请直接使用该类型并将其写出。它太过微妙了(并且有超出C ++ 14的提议来改变这个事实,所以希望你可以用C ++ 17或类似的东西来写这个。)
std::initializer_list<TypeOfExpr>
如果你想保护自己免受缩小转换(即意外地从T v {expr};
转到1000
),或者你想初始化一个具有初始化列表构造函数的类,或者你有一个聚合您要初始化的成员,使用此表单。或者,如果您正在处理初始化列表构造函数,聚合或简单的非类类型,则可以使用以下内容
char
我不使用它来调用任意构造函数。我会使用以下表格
T v = { expr };
然而,也有人喜欢使用括号形式。我想知道我的代码是做什么的,因此当我想调用一个构造函数,并且不想随意进行聚合或列表初始化构造函数调用时,我使用parens而不是braces。
答案 1 :(得分:5)
auto v = expr; T v = expr;
很好,但在自动版中,可能很难理解expr
的类型。
例如,在auto x = snafuscate();
中,x
??
如果存在歧义,最好明确声明右侧的类型为:auto x = Gadget { snafuscate() };
...
auto v(expr);
和T v(expr);
是一个坏主意,因为有效的expr
也可以理解为函数指针。
此代码无法编译:
int main()
{
int x(int());
return x + 3;
}
prog.cpp:4:11: error: invalid conversion from ‘int (*)(int (*)())’ to ‘int’ [-fpermissive]
return x + 3;
^
...
auto v { expr };
几乎总是错误的,因为v的类型变为initializer_list而不是T.
查看有关自动的最佳做法:http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/
答案 2 :(得分:5)
除了含义不同的情况(例如vector<int> v(12)
没有给出一个值为12的向量),编译器应该为上述所有内容提供相同的东西,它确实是只是个人偏好决定哪个是“更好”。
auto
非常有用,并且从上下文中可以清楚地看到类型。但auto x = 12;
很难判断它是签名还是未签名,例如[我不知道规则,可能签名]。
答案 3 :(得分:2)
我认为,不需要使用auto作为
auto x = 12332; // or
auto z = 0xffff; //
由于,
auto x = 12332; // type is 'int'
auto x2 = 0xffff // type is 'int'
auto y = 0xffffffff; // 8 fs, type is unsigned int
auto z = 0xfffffffff;// 9 fs, type is long long
auto t = 0xffffffffffffffff; // 16 fs, type is unsigned long long.
但是,你可以使用
auto size = array.size();
答案 4 :(得分:2)
这是一个非常困难的问题。
有两个不同的问题。
首先是否使用类型推导,即使用auto
说明符或明确指定类型。一般来说,我会说最好明确指定类型以帮助提高可读性,除非类型很长且很麻烦(例如迭代器):
auto it = vec.begin();
或者初始化程序中的类型是否明显:
auto pfoo = new Foo(x,y,z);
或者如果您不关心可读性。
第二种是使用什么类型的初始化。有直接初始化,复制初始化和列表初始化 - 初始化的行为在很大程度上取决于目标的类型。它们之间的差异在C ++标准的8.5节中描述。初始化也出现在更多地方而不仅仅是简单的声明。初始化发生在参数传递,返回值,子表达式,语句条件,数组边界和许多其他地方。这真的是你需要了解的细节,一些简短的总结不会削减它。