【问题标题】:Why I don't get compiling error when assigning const ptr to const reference?为什么将 const ptr 分配给 const 引用时不会出现编译错误?
【发布时间】:2019-06-27 12:06:54
【问题描述】:

我正在做一个项目并且得到一个我不理解的“奇怪行为”,它是关于传递 const ptr 来分配 const ref(或 const ptr 作为 const ref 参数)确实编译但为什么/如何? (我只是想明白) 我为测试做了一个较小的示例代码。 PS:如果有错误/误解,对不起,我不是英语母语人士

我用 -Wextra -Wall 编译

class dummy
{
public:
  dummy(const bool &run): _dummy_run(run){}
  void printRun()
  { std::cout << "RUN: " << _dummy_run << std::endl; }
private:
  const bool &_dummy_run;
};

int main(int ac, char **av)
{
  const bool *nullboolean = nullptr;
  const bool *booleanptr = new bool(true);

  /// Question 1
  /// How / why passing a const ptr to a const reference is valid ?
  dummy dummy_null(nullboolean);
  dummy dummy_new(booleanptr);

  /// Question 2
  /// Why passing const ptr to const ref is allowed but not ptr to ref ?
  const bool &cboolean = booleanptr;

  // bool &boolean = booleanptr;
  // => error: cannot bind non-const lvalue reference of type ‘bool&’ to an rvalue of type ‘bool’                                                                                   

  /// Question 3
  /// What happened here (print 191) ? There isn't any error on valgrind
  dummy_null.printRun(); // Print 191                                                       
  dummy_new.printRun(); // Print 1                                                                                 

  return 0;
}

我的问题是为什么它在将 const ptr 传递给 const 引用时编译成功? 为什么它使用 const 参考编译而不是普通参考? 为什么在打印布尔值时我有一个像“191”这样的打印值(见代码)? (期望 0、1 或 valgrind 上的错误) 如果有人可以向我解释或有一个链接来了解这里发生了什么,我会很高兴? 谢谢!

【问题讨论】:

标签: c++


【解决方案1】:

这里发生了两件事。两者都是废话,都不是你的错。

首先,当您获取 const bool* 并将其传递给采用 const bool&amp; 的构造函数时,编译器知道您没有取消引用它,因此它会寻找一种方法来继续执行您所要求的操作。

它可以通过检查指针是否为nullptr(就像使用if (booleanptr) 一样)来获得bool隐式(即没有强制转换)。然后,该临时 bool 用于初始化构造函数/函数参数中的引用,它可以这样做,因为它是 const 引用。

这已经够糟糕了。

不过,第二个是您从该引用中初始化了一个 member,但它立即悬空,因为临时的生命周期并没有延长 那么。当构造函数调用结束时它会死掉。这就是打印输出奇怪的原因:您通过尝试使用悬空引用来做未定义的事情。

(实际上,现在内存中的位模式可能不是实现识别为“真”或“假”的位模式;事实上我敢打赌它在内部使用'0'和'1'并且只是输出bool 的 int 版本。但这是实现的选择,其他任何事情都可能发生。)

所有这些混乱来自两件事:

  • 您的指针类型和引用类型 (bool) 恰好相同;
  • C++ 有你看不到的愚蠢的透明转换!

【讨论】:

    【解决方案2】:

    为什么将 const ptr 传递给 const 引用时编译成功?

    编辑:因为您的指针正在转换为临时的bool ,所以您的引用设置为临时的false 用于nullptr,否则设置为临时的true

    为什么我有一个像“191”这样的打印值

    编辑:因此,当您打印时,此临时文件已超出范围,因此您的指针取消引用是未定义的行为。

    【讨论】:

    • const bool* 是否可以隐式转换为 const bool&amp; 而无需取消引用,这一点并不明显。我想真正发生的是正在测试指针是否为空,然后结果是生命周期延长以初始化 ref
    • @LightnessRacesinOrbit 非常正确 - 错过了它没有被尊重。编辑答案。
    • 答案的第二部分仍然是错误的。一旦更正,它将只是我的一个较短的版本;)
    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 2023-04-02
    • 1970-01-01
    • 2020-04-12
    • 2021-03-12
    • 2018-03-16
    相关资源
    最近更新 更多