含引用成员的类初始化vector报错,疑惑成员是否复制实例
问题描述
想要创建一个可被vector所有元素共享的单个DebugPrinter_t实例,vector的元素类型PollingConfig_t的构造函数需要传入引用参数,但初始化vector时编译报错。
相关代码
元素类型定义:
// vector中每个元素的类型 class PollingConfig_t { public: PollingConfig_t(DebugPrinter_t& _debugPrinter) : _debugPrinter(debugPrinter) {} private: DebugPrinter_t& _debugPrinter; // 指向DebugPrinter_t全局实例的引用 };
全局变量与vector初始化:
DebugPrinter_t DebugPrinter(true); // 被vector所有元素共享的单个实例 std::vector<PollingConfig_t> PollingConfigs(4, PollingConfig_t(DebugPrinter)); // 期望创建4个持有DebugPrinter引用的PollingConfig_t实例
编译错误
error: use of deleted function 'PollingConfig_t& PollingConfig_t::operator=(const PollingConfig_t&)'
移除成员变量的&符号后代码可正常运行:
private: DebugPrinter_t _debugPrinter; // 不再是引用
但疑惑:此时是否会为vector的每个元素创建原DebugPrinter实例的副本?毕竟_debugPrinter不再是引用。
原因分析与解决方案
编译错误的原因
你使用的vector构造函数(std::vector<T>(size_t count, const T& value))会先以传入的value为原型,通过拷贝赋值操作创建count个元素。但C++标准规定:如果类包含引用成员,编译器会自动删除默认的拷贝赋值运算符(operator=)——因为引用一旦绑定到某个对象就无法重新绑定,赋值操作无法实现合理语义,因此编译器直接禁用了该运算符,最终导致构造vector时触发错误。
另外注意:你原构造函数的初始化列表存在拼写错误,应修正为_debugPrinter(_debugPrinter),否则会因未定义的debugPrinter标识符引发额外问题。
正确实现共享实例的方法
要让vector每个元素都持有同一个DebugPrinter的引用,需避免触发拷贝赋值操作,改用直接在vector内存中构造每个元素的方式,比如使用emplace_back:
DebugPrinter_t DebugPrinter(true); std::vector<PollingConfig_t> PollingConfigs; PollingConfigs.reserve(4); // 提前分配内存,避免后续扩容 for (int i = 0; i < 4; ++i) { PollingConfigs.emplace_back(DebugPrinter); // 直接在vector空间内构造对象,传递引用参数 }
emplace_back会直接调用PollingConfig_t的构造函数在vector内存中创建对象,无需拷贝或赋值,既不会触发被删除的拷贝赋值运算符,又能让每个元素的引用正确绑定到全局的DebugPrinter实例。
关于副本的疑问
当你移除&符号,将成员变量改为DebugPrinter_t _debugPrinter时,每个vector元素确实会创建一个DebugPrinter的副本。此时成员是对象而非引用/指针,构造PollingConfig_t时会调用DebugPrinter_t的拷贝构造函数,把全局DebugPrinter实例复制一份到每个PollingConfig_t对象中,完全不符合你“共享单个实例”的需求。
内容的提问来源于stack exchange,提问作者AMG

