我这样做了吗?这是我的代码的高度简化版本:
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)
时会执行什么?
答案 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&