【问题标题】:What's the difference between type(myVar) and (type)myVar?type(myVar) 和 (type)myVar 有什么区别?
【发布时间】:2010-08-14 17:25:47
【问题描述】:

我正在 cplusplus.com 上阅读完整的教程,手动编码和编译每个示例。我经常会偶然发现一些让我感到困惑的事情。

我目前正在学习这个部分:http://www.cplusplus.com/doc/tutorial/structures/。仅阅读本教程很容易忽略一些细微之处。手动输入所有内容的好处是这些细节确实很突出。

在上面的页面中,有两个示例程序。有这一行:

stringstream(mystr) >> yours.year;

另一个有这样一行:

(stringstream) mystr >> pmovie->year;

我不明白type (myVar) = x;(type) myVar = x; 之间的区别(如果有的话)。

我没有按顺序完成整个教程。我查了一下,但没有找到这个地址,虽然我可能错过了。

  • 有区别吗?
  • 有没有一种首选的方法来做这件事而不是另一种?

【问题讨论】:

  • 它不是一个函数,而是一个类。第一个调用是构造函数调用,第二个调用是转换运算符调用。

标签: c++


【解决方案1】:

type(x)(type)x 之间没有区别。这两个是完全等价的。大多数人更喜欢type(x) 用于类,(type)x 用于非类类型,但这完全取决于自己的选择。两者都为具有一个参数x 的类调用构造函数。

类的首选方式是type(x),因为这允许向构造函数传递多个参数,如type(x, y)。尝试应用另一种形式,(type)x, y 将不起作用:它强制转换 x,然后应用逗号运算符并单独评估 y。像(type)(x, y) 这样的括号没有帮助:这将使用逗号运算符单独评估xy,然后将y 转换为type

对于非类类型,这样的强制转换通常过于强大。 C++ 有static_cast<type>(x) 用于粗略地执行隐式转换的反向操作(例如将基类转换为派生类并将void* 转换为另一个指针),这通常是适合的。参见When should static_cast, dynamic_cast and reinterpret_cast be used?

stringstream 不是函数。执行function(x) 将调用它的函数,但执行(function)x 是非法的,因为有两个表达式彼此相邻,中间没有运算符。


对于那些不相信这个答案,并在直觉上投反对票的人,请通过5.2.3/1查阅标准

一个简单类型说明符(7.1.5)后跟一个带括号的表达式列表构造一个给定表达式列表的指定类型的值。如果表达式列表是单个表达式,则类型转换表达式等效于(在定义上,并且如果在含义上定义)对应的强制转换表达式(5.4)。

【讨论】:

  • @nico 这不是意见问题。该标准定义了什么是等效的,什么不是。它将这两者定义为等价的,因此由编码风格决定在什么情况下使用什么。
  • 这不是神经科学:这些问题完全由标准指定,人们对语言的看法与其语义无关。显然你已经对这个问题下定了决心,这很可惜,但我不想改变它。我有更好的方式来消磨时间:)
  • @nico 哦,我在开玩笑。今天是星期天,是时候找点乐子了。但说真的,标准说两件事是等价的——我认为这是一个明确的声明。我不认为它可以解释。如果您能展示一个代码示例,清楚地显示这两种形式之间的行为不同之处,我会很高兴。我想我同意它们 在词法上 不同,就像 150xf 是“不同的”一样,但这有什么关系呢?输入十进制还是十六进制完全取决于自己的选择。
  • @nico 我想说的是两者都是演员表。两者都为类调用构造函数,而不为非类调用构造函数。你可以说 int(some_pointer) 和 (int)some_pointer。我认为说一种形式将调用构造函数而另一种形式将是强制转换没有任何价值,因为它暗示了一些不存在的差异。 int(some_pointer) 中没有构造函数调用。我可以将10 称为“创造”,将0x10 称为小数的“转换”,因为语法看起来很可爱,但这并不会改变它的语义。这完全是主观的。
  • hell 否决了这个答案?
【解决方案2】:

您引用的页面不是我一般认为的 C++ 权威。

不管怎样,

(stringstream) mystr >> pmovie->year;

std::string 转换为std::stringstream 对象。这是一个 C 风格的演员表。如果你不知道自己在做什么,那就太危险了。这将创建一个stringstream 对象,并将值提取到pmovie->year next。

stringstream(mystr) >> yours.year;

创建一个匿名的std::stringstream 对象并用mystr 对其进行初始化,然后将值提取到pmovie->year。该对象在其词法范围的末尾消失,在这种情况下,该词法范围将是行尾的;

这两个 w.r.t 类对象之间没有太大区别(正如其他人所指出的那样)。

另一方面,对于(函数/宏的)标识符,这会变得很棘手:function (myVar) = x; 的工作原理与 function 是实际函数还是宏无关。但是,(function) (myVar) = x; 仅适用于实际功能。

一些标准库标识符允许同时具有两种形式(最值得注意的是tolower 和朋友),因此如果您想始终调用该函数,那么您应该使用前者。

【讨论】:

  • cplusplus.com 有什么问题?我一直使用他们的参考资料。
  • 当然是个人意见。 OP 的问题就是一个很好的例子。
  • 您的回答表明两种形式之间存在差异,但没有详细说明这种差异。它还表明格式错误的表达式 (function) myVar 将是有效的(而不是 (function)(myVar))。
  • 感谢您的回复。我很高兴我问了。我现在明白了很多。关于 cplusplus.com:您会推荐哪些在线 C++ 教程替代品?我只是偶然发现了learncpp.com,它看起来更完整。我还使用 cplusplus.com 作为标准库参考:cplusplus.com/reference。如果你知道更好的 C++ 标准库参考网站,也请告诉我。
  • 作为参考:我更喜欢 SGI STL 网站和 MSDN 参考(尽管这些示例有时非常丑陋)。尝试一本书(Stroustrup 写的东西)通常被认为是一个好的开始。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 1970-01-01
  • 2015-07-17
相关资源
最近更新 更多