在Scott Meyer的书“Effective Modern C ++”中,我们可以阅读:
std::vector<bool> features(const Widget& w);
Widget w;
…
bool highPriority = features(w)[5];
…
processWidget(w, highPriority);
和auto
选项auto highPriority = features(w)[5];
导致未定义的行为,因为features()
正在返回std::vector<bool>
,在从std::vector<bool>::reference
返回值时使用类型为opearator[]
的代理对象。 / p>
建议不要停止使用auto
,而是使用static_casts
来解决此问题。
Scott Meyers建议使用:
auto highPriority = static_cast<bool>(features(w)[5]);
而不是:
bool highPriority = features(w)[5];
我的问题是: 这两者之间真正的区别是什么?在我看来两者都是相同的,因为两种方法都以完全相同的方式使重构变得更难(在函数功能中改变返回值类型不会使变量highPriority成为不同的类型)而第二种方法的写入时间更短。
答案 0 :(得分:7)
如果您不喜欢features
的界面,可以隐藏辅助功能中的丑陋
bool is_high_priority(const Widget& w)
{ return features(w)[5]; }
现在你的
auto highPriority = is_high_priority(w);
按预期工作。
答案 1 :(得分:5)
使用features
函数返回std::vector<bool>
,
auto highPriority = features(w)[5];
存储逻辑参考。存储的对象是指不再存在的向量。使用它然后会产生未定义的行为。
取而代之的是
bool const highPriority = features(w)[5];
或
auto const highPriority = !!features(w)[5];
或者,正如斯科特所建议的那样 - 但根据我的口味,它太冗长了 - 请使用static_cast
。
存储的对象现在是bool
。
这三种表达同一声明的方式之间没有功能差异。唯一的区别是不起作用的:在我看来static_cast
的不必要的冗长,以及!!
可能会从一个常见的编译器中抑制关于性能的愚蠢警告。
答案 2 :(得分:0)
当你使用auto时,auto会将它推断为highPriority返回的类型,它是对bool的引用。问题是,highPriority不会返回对bool的引用,而是返回对std :: vector :: reference对象的引用。 (&#39; reference&#39;是std :: vector中的嵌套类)。 std :: vector :: reference是一个&#34;代理类&#34;,一个模拟其他类型行为的类。它不仅是一个代理类,而且是一个不可见的&#34;代理类。这些类与auto不兼容。 Auto无法正确推断出不可见代理类的类型。但是static_cast强制将高优先级转换为bool。这可以避免未定义的行为。