初始化对象成员,并在初始化列表中引用

时间:2012-01-13 11:03:00

标签: c++ constructor initialization

我这样做了吗?这是我的代码的高度简化版本:

class Logger {
   public:
      Logger(std::ostream) { /*...*/}
};

class Driver {
public:
   Driver() : m_logger(std::cout) {}
   Driver(Logger& logger) : m_logger(logger) {}
private
   Logger m_logger;
};

因此我的班级Driver的成员类型为Logger。当我调用无参数构造函数Driver()时,Driver的实例使用Logger创建自己的std::cout实例。

当调用Driver(Logger)时,实例应使用已作为参考传递的Logger已存在的实例。

上面的代码使用g ++编译。虽然我理解在调用Driver()时会发生什么,但我不知道在调用Driver(Logger)时会发生什么。 Logger没有构造函数接受Logger上的引用作为参数(“复制构造函数”)。那么在调用Driver(Logger)时会执行什么?

2 个答案:

答案 0 :(得分:2)

当您使用Driver参数构造Logger时,它将通过引用获取并调用Logger复制构造函数来初始化m_logger,因此您最终会一个新的Logger,它是参数的副本。复制构造函数由编译器提供,除非您通过声明复制构造函数Logger明确地使private不可复制。

似乎完全有效,但您应该将logger参数设为const参考;你打算复制它,毕竟不要修改它。

答案 1 :(得分:2)

Logger的一个简单的复制构造函数是为你合成的,除非你自己声明一个。

这与为您合成一个简单的默认构造函数(如果您没有声明默认的用户定义构造函数)非常相似。


  

[C++11: 12.8/7]: 如果类定义没有显式声明复制构造函数,则会隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数   被定义为删除;否则,它被定义为默认值(8.4)。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。因此,对于类定义

struct X {
   X(const X&, int);
};
     

隐式声明了复制构造函数。如果用户声明的构造函数稍后定义为

X::X(const X& x, int i =0) { /* ... */ }
     

然后由于模糊性,X的复制构造函数的任何使用都是格式不正确的;无需诊断。

  

[C++11: 12.8/8]:X的隐式声明的复制构造函数将具有

形式
X::X(const X&)
     

如果

     
      
  • B的每个直接或虚拟基类X都有一个复制构造函数,其第一个参数的类型为const B&const volatile B&,并且
  •   
  • 对于类X(或其数组)的M的所有非静态数据成员,每个此类类型都有一个复制构造函数,其第一个参数的类型为{{ 1}}或const M&
  •   
     

否则,隐式声明的复制构造函数将具有

形式
const volatile M&