【问题标题】:is there any risk using std::addressof(std::cout) instead of &std::cout?使用 std::addressof(std::cout) 代替 &std::cout 有什么风险吗?
【发布时间】:2020-05-28 21:46:50
【问题描述】:

我正在使用std::cout 进行日志记录,并且当“不要获取 'cout' 的地址,而是从 lambda 调用它”时,sonarqube 会报告错误。

std::ostream *streamp;
streamp = &std::cout;

当我使用下面的代码时,在 sonarqube 中没有观察到错误。在std::cout 函数上使用std::addressof 是否安全?

std::ostream *streamp;
streamp = std::addressof(std::cout);

【问题讨论】:

  • 安全性和使用&一样;分析仪不够聪明,无法看到发生了什么。我想知道这个警告的原因是什么......
  • 这是一个非常奇怪的警告。 cout 是一个静态对象,保证在您的任何代码之前被初始化,因此获取指向它的指针应该是 100% 安全的。
  • 我怀疑这是一个试图捕捉 [&std::cout](){ cout << "Capturing a name unnecessarily"; } 等的警告。
  • @NathanOliver 如果静态对象在关机期间进行日志记录并且cout 在记录器销毁之前被销毁,那么可能会出现问题?
  • @M.M 我认为这不会发生:timsong-cpp.github.io/cppwp/…

标签: c++ c++11 sonarqube c++14


【解决方案1】:

是的,在 std::cout 上使用 addressof 是安全的。但是由于在std::cout 上使用& 同样安全,所以这样做的唯一原因是让一个明显给你误报的工具安静下来(它没有意识到addressof 在做什么) .

最好使用& 并使用工具中存在的任何机制来关闭误报。

【讨论】:

    【解决方案2】:

    std::cout 是一个对象,而不是一个函数,因此禁止获取大多数标准函数地址的规则不适用。

    std::addressof() 仅在地址运算符可能超载的情况下才需要(通常甚至考虑都是一件坏事),因此在模板中使用以避免意外。任何标准类型都不需要它,因此也不需要它。

    总之,修复工具或忽略该警告,这是您的选择,但不要将您的代码弯曲成椒盐卷饼。


    为了扩展标准函数,标准库中的大多数函数都没有被指定为“可寻址”。
    因此,获取它们的地址可能会导致意外,从偶然的“工作”,到提供具有意外签名的函数指针(更多参数,意外调用约定,等等),到根本无法编译。这可能会随着工具链的任何变化而改变。

    【讨论】:

    • 我同意你的一般分析,但实际上是不是既然std::cout是一个对象,我们就不用担心取地址了?原则上它可能有一个重载的& 运算符,尽管我的猜测(?)是标准不允许这样做?
    • @templatetypedef 澄清了标准类型在这方面是合理的。
    【解决方案3】:

    &xstd::addressof(x) 之间的区别(对于类类型的变量)只有在 x 具有重载的 & 运算符时才会出现。

    addressof 的意思是“不,不,我真的想要这东西的地址,不管班级设计者有什么规定”。

    话虽如此,99++% 的时间&x 都很好。 cout 肯定没问题,因为您可以查看并看到它没有 operator &

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-27
      • 2010-10-12
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      相关资源
      最近更新 更多