在安置中的危险隐含转换

use*_*667 7 c++ c++11

以下代码使用gcc 6.3(https://godbolt.org/g/sVZ8OH)编译时没有任何错误/警告,但由于下面标记的内存访问无效,它包含危险的未定义行为.根本原因是在emplace_back中执行的隐式转换.任何人都可以建议一个好的方法或最佳做法,以避免代码中的此类错误?

#include <iostream>
#include <vector>

struct Foo
{
  explicit Foo(const int& i) : i{i} {}

  void foo() const { std::cout << i; }  // invalid memory access, as i is an invalid ref!!
  const int& i;
};

void bar(const double& d) {
  std::vector<Foo> fv;
  fv.emplace_back(d);
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ica 12

如果你要接受一个const参考,但你希望一个临时参考,宣布与右值引用参数附加构造-并将其删除.

struct Foo
{
  explicit Foo(const int& i) : i{i} {}
  explicit Foo(const int&& i) = delete;  // This preferentially matches a reference to a
                                         // temporary, and compilation fails.

  void foo() const { std::cout << i; }  // invalid memory access, as i is an invalid ref!!
  const int& i;
};
Run Code Online (Sandbox Code Playgroud)

(我假设实际问题比一个int更复杂.对于一个int,按值保持它是正确的答案.)


R S*_*ahu 4

任何人都可以建议一种好方法或最佳实践来避免代码中出现此类错误吗?

当您的类存储const对另一个对象的引用时,作为程序员,您有责任确保最终不会存储悬空引用。

除非您有充分的理由存储const引用,否则我建议存储一个值。

struct Foo
{
  explicit Foo(const int& i) : i{i} {}

  void foo() const { std::cout << i; }
  int i;
};
Run Code Online (Sandbox Code Playgroud)

  • @latedeveloper:是的,但是创建对临时对象的 const 引用要容易得多(它很快就会变成悬空引用)。非常量引用必须指向左值(它*可以*成为悬空 - 但可能性较小)。 (2认同)