【问题标题】:Typedef const reference from a pointer [duplicate]来自指针的Typedef const引用[重复]
【发布时间】:2012-01-10 16:33:18
【问题描述】:

可能重复:
Why is it allowed to cast a pointer to a reference?

为什么会编译:

class Bar {};

int main() {
  Bar i;
  Bar *b = &i;
  typedef const Bar& type;
  type t = type(b);
}

G++(4.5,4.7 个快照)、Comeau 和 MSVC 都很高兴,但警告未使用的变量。

编译器认为这意味着什么?是UB吗?为什么不是错误?

我认为这应该是一个错误,因为我不小心将Bar* 变成了const Bar&,而没有取消引用或疯狂转换。我认为这一切都是完全安全的。

【问题讨论】:

  • 请将其缩减为最小代码,例如从const type t 中删除const
  • 也许你也应该写下为什么你认为它应该是一个错误?
  • 我明白了:warning: dereferencing type-punned pointer will break strict-aliasing rules。而更合适的const type t(b);确实是个错误。但你是对的,为什么会自动取消引用?
  • @ronag: 很明显,你不能从Bar* 初始化Bar const&const type 也不应该存在,但我认为 const 无论如何都会被类型别名忽略。
  • @AzzA:这是一个毫无意义且无益的断言。

标签: c++


【解决方案1】:

C 风格的转换依次尝试不同的 C++ 转换类型:

[C++11: 5.4/5]: 完成的转化

  • const_cast (5.2.11),
  • static_cast (5.2.9),
  • static_cast 后跟 const_cast
  • reinterpret_cast (5.2.10),或
  • reinterpret_cast 后跟 `const_cast

可以使用显式类型转换的强制转换表示法来执行。 应用相同的语义限制和行为,除了在以下情况下执行 static_cast 时转换是有效的,即使基类不可访问:

  • [..]

然后遵循我懒得详细解析的各种复杂规则。

你会得到必要的警告,说这是一个愚蠢的演员,但既然这是你要求的,那就是尝试的。

比较:

class Bar {};

int main() {
  Bar *b = 0;
  typedef const Bar& type;
  const type t = static_cast<type>(b);
}

// In function 'int main()':
// Line 6: error: invalid static_cast from type 'Bar*' to type 'const Bar&'
// compilation terminated due to -Wfatal-errors.

【讨论】:

  • 这不是 C 风格的演员表,你不能用 C 写 double(0)
  • @awoodland : 重要的是 (T)vT(v) 在语义上是相同的,我相信我们可以同意前者是一个演员表。
  • @awoodland:“可以使用显式类型转换的强制转换符号来执行。” double(0)(double)0 都是“显式类型转换的强制转换符号”。两者的作用完全相同。
  • @ildjarn - 看起来可能是这样,但这有点令人担忧:我假设T(v) 总是具有复制构造函数语义,即使对于原语 - 这使得“避免 C 风格使“在代码中更难发现”一个数量级。
  • 我希望语言有一个明确的stupid_cast&lt;T&gt;...
【解决方案2】:

因为你正在向它投射。

class Bar {};

int main() {
  Bar *b = 0;
  typedef const Bar& type;
  const type t = b;
  (void)t;
}

上面的例子吐出下一个错误:

error: invalid initialization of reference of type 'type {aka const Bar&}' from expression of type 'Bar*'

【讨论】:

  • 这并不能解释为什么演员会成功。
【解决方案3】:

似乎引用可以转换为指针。你的表达本质上是,

Bar & r = reinterpret_cast<Bar&>(b);

但在这种明确的形式中,我收到 两个 警告:

warning: casting ‘Bar*’ to ‘Bar&’ does not dereference pointer [enabled by default]
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

但这似乎不是错误。

【讨论】:

    猜你喜欢
    • 2021-12-31
    • 2011-01-16
    • 2011-01-10
    • 2019-06-27
    • 2011-03-04
    相关资源
    最近更新 更多