在原位进行危险的隐式转换

Dangerous implicit conversion in emplace

本文关键字:转换 危险      更新时间:2023-10-16

以下代码在 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);
}

如果要接受 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,按值持有它是正确的答案。

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

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

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

struct Foo
{
  explicit Foo(const int& i) : i{i} {}
  void foo() const { std::cout << i; }
  int i;
};