应该将C ++ 11中的所有/大多数setter函数写成接受通用引用的函数模板吗?

考虑一个具有N成员variables的类X ,每个variables都是 复制的可移动的 ,以及N相应的设置函数。 在C ++ 98中, X的定义可能如下所示:

 class X { public: void set_a(A const& a) { _a = a; } void set_b(B const& b) { _b = b; } ... private: A _a; B _b; ... }; 

上面的类X Setter函数可以绑定到左值和右值参数。 根据实际的参数,这可能会导致创build一个临时的,最终会导致一个副本分配; 由于这个原因,这种devise不支持不可复制的types。

使用C ++ 11,我们可以移动语义,完美转发和通用引用(Scott Meyers的术语),通过以这种方式重写它们,可以更有效地使用setter函数:

 class X { public: template<typename T> void set_a(T&& a) { _a = std::forward<T>(a); } template<typename T> void set_b(T&& b) { _b = std::forward<T>(b); } ... private: A _a; B _b; ... }; 

通用引用可以绑定到const /非常量, volatile /非易失volatile和一般的任何可转换types,避免创build临时值并将值直接传递给operator = 。 现在支持不可复制的 可移动types。 可能不需要的绑定可以通过static_assert或通过std::enable_if来消除。

所以我的问题是:作为一个devise指南 ,C ++ 11中的所有(比如说,大多数)setter函数应该被写为接受通用引用的函数模板吗?

除了在这些设置函数中编写代码时使用类似于Intellisense的帮助工具的更麻烦的语法和不可能性之外,假设的原则“ 写setter函数作为函数模板接受通用引用(尽可能) ”有什么相关的缺点吗?

你知道A和B类,所以你知道他们是否是可移动的,如果这种devise是最终的必要的。 对于像std::string这样的东西,除非你知道这里有性能问题,否则改变现有的代码是浪费时间的。 如果你正在处理auto_ptr ,那么是时候把它unique_ptr出来并使用unique_ptr

如果你不知道什么更具体的话,现在通常倾向于采取有价值的论据

 void set_a(A a) { _a = std::move(a); } 

这允许使用A的任何构造器,除了可移动性之外不需要任何东西,并提供相对直观的界面。