如何避免按引用传递的参数被意外复制?C++技术问询
问题场景与疑问
假设我们有一个非临时的int值,要求Foo类的实例仅引用它、而非复制它。正确的实现应该是把成员定义为const int&:
class Foo { public: Foo(const int& reference) : mReference(reference) { } private: const int& mReference; };
但如果不小心把成员定义成了int而非const int&,构造时就会意外复制参数:
class Foo { public: Foo(const int& reference) : mReference(reference) // 这里会发生意外复制,需要避免 { } private: // 成员被误定义为int而非const int& int mReference; };
由此产生两个疑问:
- 能不能通过调整构造函数参数的定义,避免这类意外复制?
- 标准库中有没有类似
std::unique_ptr、专门针对引用且不需要动态内存分配的工具?
解决方案与说明
一、通过构造函数参数避免意外复制
当然可以,你可以用std::reference_wrapper来约束构造函数参数,让编译器在成员被误定义时直接报错,从源头阻止复制。
把构造函数的参数改成std::reference_wrapper<const int>,这样如果成员被误写成int,编译器会因为无法将std::reference_wrapper隐式转换为int而报错,根本不会走到复制那一步:
#include <functional> class Foo { public: Foo(std::reference_wrapper<const int> ref) : mReference(ref) { } private: const int& mReference; // 正确定义 }; // 要是误把成员改成int,编译直接报错: // class Foo // { // public: // Foo(std::reference_wrapper<const int> ref) : // mReference(ref) // 错误:无法将std::reference_wrapper<const int>转换为int // { // } // private: // int mReference; // };
这种方式利用编译期检查提前拦截错误,比运行时发现问题靠谱得多。
二、标准库中的引用专用工具
标准库里的std::reference_wrapper就是你要找的东西——它专门用来包装引用,完全符合「类似std::unique_ptr针对引用、无需动态内存分配」的需求:
- 它是轻量级对象,内部只存引用的地址,不需要动态分配内存;
- 可以像普通引用一样使用,但能被放进STL容器里(普通引用做不到);
- 用
std::ref(非const引用)或std::cref(const引用)就能快速创建实例。
比如直接把成员定义成std::reference_wrapper<const int>,同样能杜绝意外复制:
#include <functional> class Foo { public: Foo(const int& ref) : mReference(std::cref(ref)) { } private: std::reference_wrapper<const int> mReference; };
要是这时误把成员改成int,初始化时std::cref(ref)返回的std::reference_wrapper没法隐式转成int,编译器直接报错,彻底避免了复制风险。
内容的提问来源于stack exchange,提问作者Dmitry Sapelnikov
相关产品推荐
相关产品推荐

