【问题标题】:Initialize member reference with default value使用默认值初始化成员引用
【发布时间】:2018-06-12 18:18:12
【问题描述】:

我有一个带有std::vector const& 成员的类,该成员应通过构造函数进行设置。但是,也应该可以在构造函数中省略这个参数,让成员用默认值初始化。

示例代码:

class MyClass {
public:
  MyClass(int a, const std::vector<int> &v = {42,42,42}) : vec(v){}

  const std::vector<int> &vec;
};

int main(void) {

  std::vector<int> a{1,2,3};

  MyClass c1(1,a);              // c1.vec = 1,2,3
  MyClass c2(1);                // c2.vec = randomStuff
                                // should actually be 42,42,42
}

如果我将初始化更改为:

MyClass(int a, const std::vector<int> &v = *(new std::vector<int>{42,42,42})) : vec(v){}

一切正常,因为超出范围时临时向量不会被删除。但是,这感觉不对,并且看起来内存泄漏。有没有更明智的方法来实现预期的行为?

【问题讨论】:

  • 请注意,它不只是看起来内存泄漏,它确实会泄漏内存。
  • 您确定持有 reference 成员真的是您想要做的吗?确保你的对象生命周期完全正确!

标签: c++ constructor default-arguments


【解决方案1】:

您可以将默认参数定义为类的静态数据成员:

class MyClass {
 public:
  MyClass(int a, const std::vector<int> &v = defaultVec) : vec(v){}

  const std::vector<int> &vec;

 private:
  static const std::vector<int> defaultVec;
};

const std::vector<int> MyClass:defaultVec{42, 42, 42};

要保留类头文件,您还可以在静态成员函数中使用静态变量:

class MyClass {
 public:
  MyClass(int a, const std::vector<int> &v = defaultVec()) : vec(v){}

  const std::vector<int> &vec;

 private:
  static const std::vector<int>& defaultVec()
  {
   static const std::vector<int> v {42, 42, 42};
   return v;
  }
};

请注意,无论哪种方式,用作默认参数的向量都必须具有静态存储持续时间,以便在构造函数完成运行后保持有效。

【讨论】:

  • 我认为可以通过解释为什么需要静态成员以及引用类型成员的风险和后果(例如防止分配和移动语义以及生命周期管理问题)来改进这个答案)。
  • 考虑内联变量(或 C++17 之前的技巧)以允许类仅作为标题(与原始类一样)
  • @FrançoisAndrieux 同意对静态的解释,不同意参考部分 - OP 已经使用参考,我们没有理由假设他们不确定潜在的陷阱。
猜你喜欢
  • 1970-01-01
  • 2019-09-10
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-22
  • 2017-11-22
  • 1970-01-01
相关资源
最近更新 更多