在安置中的危险隐含转换

时间:2016-12-30 21:14:24

标签: 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);
}

2 个答案:

答案 0 :(得分:12)

如果您要接受const引用,但想要引用临时引用,请声明带有rvalue引用参数的其他构造函数 - 并将其删除。

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;
};

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

答案 1 :(得分:4)

  

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

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

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

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

  void foo() const { std::cout << i; }
  int i;
};