自动和静态\u转换-良好实践 < Scott Meyer的书中,我们可以阅读现代的C++,即: std::vector<bool> features(const Widget& w); Widget w; … bool highPriority = features(w)[5]; … processWidget(w, highPriority);

自动和静态\u转换-良好实践 < Scott Meyer的书中,我们可以阅读现代的C++,即: std::vector<bool> features(const Widget& w); Widget w; … bool highPriority = features(w)[5]; … processWidget(w, highPriority);,c++,c++11,coding-style,C++,C++11,Coding Style,这会导致未定义的行为,因为features()正在返回std::vector,从opearator[]返回值时使用类型为std::vector::reference的代理对象 作为解决方案,建议不要停止使用auto,而是使用static\u casts 因此,Scott Meyers建议使用: auto highPriority = static_cast<bool>(features(w)[5]); 我的问题是: 这两者之间的真正区别是什么?在我看来,这两种方法都是一样的,因为这

这会导致未定义的行为,因为
features()
正在返回
std::vector
,从
opearator[]
返回值时使用类型为
std::vector::reference
的代理对象

作为解决方案,建议不要停止使用
auto
,而是使用
static\u casts

因此,Scott Meyers建议使用:

auto highPriority = static_cast<bool>(features(w)[5]);
我的问题是:
这两者之间的真正区别是什么?在我看来,这两种方法都是一样的,因为这两种方法以完全相同的方式使重构更加困难(更改函数特性中的返回值类型不会使变量高优先级成为不同的类型),第二种方法编写起来更短。

使用
特性
一个返回
std::vector
的函数

存储逻辑引用。存储的对象引用了一个不再存在的向量。使用它会导致未定义的行为

取而代之的是

bool const highPriority = features(w)[5];

或者,正如Scott所建议的——但对我来说太冗长了——使用
static\u cast

存储的对象现在是
bool


这三种表达相同声明的方式在功能上没有区别。唯一的区别是非功能性的:在我看来,
静态播放的不必要的冗长,还有一种可能性是
可能会抑制来自一个常见编译器的关于性能的愚蠢警告。

如果您不喜欢
功能的接口,您可以在助手函数中隐藏其丑陋之处

bool is_high_priority(const Widget& w)
{ return features(w)[5]; }
现在你的

auto highPriority = is_high_priority(w);

按预期工作。

使用auto时,auto将其推断为highPriority返回的类型,highPriority是对bool的引用。问题是,highPriority不会返回对bool的引用,而是返回一个std::vector::reference对象。('reference'是std::vector中的嵌套类)。vector::reference是一个“代理类”,一个模拟其他类型行为的类。它不仅是一个代理类,而且是一个“不可见”的代理类。这样的类不能很好地与auto一起工作。Auto无法正确推断不可见代理类的类型。但是静态_cast强制将高优先级转换为bool。这避免了未定义的行为。

只是一种怀疑,但从我的头脑中我想不出功能上的差异,斯科特的唯一原因可能是一致性——他不是在同一本书的某个地方提倡使用
auto x=
来处理实际的所有事情吗。。。?(或者可能是我在网上看到的某篇文章…@TonyD是的,一致性可能是原因。他建议在第5项中“更喜欢
auto
而不是显式类型声明”,我认为第一个解决方案明确地告诉读者“事情不是布尔,但我希望它是布尔”。第二种解决方案通常会告诉读者“这是一个bool,或者至少可以这样使用”,但问题是,大多数读者将其解读为“这是一个bool”,可能是“嘿,现在我们有了
auto
,所以我们编写了
auto highPriority=features(w)[5];
!”和boom。即使两种解决方案在技术上完全相同,读者也会在第一种解决方案中得到警告,即直接使用
功能(w)[5]
可能存在问题。顺便说一下,像表达式模板这样的东西也会出现同样的问题。我就是这么说的。我问了两个可能的解决方案,为什么斯科特·迈尔斯喜欢第一个,他不喜欢。这是有区别的。他的话。。。强制转换将表达式的类型更改为bool,然后自动推断为高优先级的类型。在运行时,从std::vector::operator[]返回的std::vector::reference对象执行到它支持的bool的转换因此,静态强制转换对于将类型更改为bool是必要的,其他所有操作都要先执行。执行完全相同的强制转换,当您在第一次和第二次尝试中说
bool highPrio…
时,执行没有区别。在这两种溶液中都进行了铸造,并且铸造方式相同。一个是显式的,一个是隐式的,这是唯一的区别。结果是一样的。你能告诉我在哪里吗!!来自哪里?是新接线员还是什么?它是编译器特有的功能吗?不管怎么说,我都找不到它,它只是连续的两个否定<代码>!x
x
转换为
bool
(通过与0进行比较),但值相反<代码>!!x将再次反转
的值!x
,为零生成
false
,为非零生成
true
bool const highPriority = features(w)[5];
auto const highPriority = !!features(w)[5];
bool is_high_priority(const Widget& w)
{ return features(w)[5]; }
auto highPriority = is_high_priority(w);