【问题标题】:What does static_cast<T> do to a T&?static_cast<T> 对 T& 有什么作用?
【发布时间】:2016-10-24 11:01:29
【问题描述】:

所以我问了this question,我正在修补通过static_cast 解决它。 (顺便说一句,它确实解决了问题,我只是不确定我是否理解为什么。)

在代码中:

vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13);

static_cast 是否只是构造一个 R 值 int?那和只是调用有什么区别:

replace(begin(foo), end(foo), int{foo.front()}, 13);

编辑:

正如static_cast的答案所推断的那样确实似乎构造了一个R值inthttp://ideone.com/dVPIhD

但此代码在 Visual Studio 2015 上工作。这是编译器错误吗?在这里测试:http://webcompiler.cloudapp.net/

【问题讨论】:

  • 我没有任何标准的引用来支持我,但我认为您可以使用 +foo.front() 来获取值的副本,而不是对符号的引用

标签: c++ casting reference rvalue static-cast


【解决方案1】:
  1. 是的,它与int{...} 相同,除非.front() 返回需要缩小转换的类型。在这种情况下,int(...) 将是相同的。

  2. 在出现程序员错误的情况下,静态转换不太可能做一些危险的事情,例如将指针转换为 int,而不是 int(...)

请注意,由于替换操作修改了前面的元素,因此消除强制转换会导致未定义的行为,这可能会破坏std::replace

我会用

template<class T>
std::decay_t<T> copy_of(T&& t){return std::forward<T>(t); }

我自己在这里。

至于为什么这在 MSVC 中不起作用...

MSVC 在您将T 类型的变量转换为T 并继续什么都不做的情况下很有帮助。这会破坏您的代码。

您可以使用compiler flag (/Zc:rvalueCast) 使 MSVC 不再破坏您的代码。

【讨论】:

  • copy_ofstandard,还是说我应该实现它?
  • “MSVC 有助于解决您将类型 T 的变量转换为 T 并继续不执行任何操作的情况。这会破坏您的代码。”lol
  • "默认情况下,/Zc:rvalueCast 是关闭的。为了一致性和消除使用强制转换的错误,我们建议您使用 /Zc:rvalueCast。"地狱
  • @Yakk:当然,我明白了,但如果他们建议打开标志,它应该默认打开。这样他们就打破了所有其他编译器行为的“遗留”行为! 需要遗留行为的用户应该被要求查找并打开它。国际海事组织。在该文档中,这似乎是一个非常奇怪的矛盾。
  • @LightnessRacesinOrbit 否。几乎每个编译器的默认行为往往是“不要破坏在此编译器的先前版本中工作的代码,没有大量警告”。您可以在 gcc 中看到这一点,它在 long 时间内没有破坏 std::string 的兼容性。从 MSVC2012 升级到 MSVC2015 的客户比来自 gcc 或 clang 的客户多得多。
【解决方案2】:

成员函数front返回对非空向量的第一个元素的引用。

另一方面,标准算法replace 声明为

template <class ForwardIterator, class T>
  void replace (ForwardIterator first, ForwardIterator last,
                const T& old_value, const T& new_value)

也通过引用获取第三个参数。因此,一般来说,算法可以改变向量的第一个元素,结果算法对向量的其他元素的处理可能是不正确的。

使用static_cast创建了一个临时对象,不会被算法改变所以对向量的所有元素的处理都是正确的。

至于我,我建议在这种情况下使用关键字 auto 的 C++ 建议。例如

replace(begin(foo), end(foo), auto( foo.front() ), 13);

【讨论】:

  • auto 的建议非常优雅。 +1
  • @NathanOliver 正如答案中所说,这只是一个建议
  • @NathanOliver 这只是我的建议。我需要先写它。我只在 ISO C++ 论坛上建议过。:)
  • 我怀疑这样的提议是否会被接受,部分原因与我们不能基于返回值重载函数的原因相同:C/C++ 中表达式的返回类型不依赖于他们将被抓到的地方。
猜你喜欢
  • 2016-11-10
  • 1970-01-01
  • 2019-04-14
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多