考虑具有X
成员变量的类N
,每个可复制和可移动类型,以及N
对应的setter功能。
在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函数可以绑定到lvalue和rvalue参数。根据实际参数,此可能导致创建临时,将最终导致复制分配;因此,此设计不支持不可复制的类型。
使用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
/非 - const
,volatile
/非 - volatile
,也可以绑定到任何可转换类型,避免创建临时引用将值直接传递给operator =
。现在支持不可复制的,可移动类型。可能会通过static_assert
或std::enable_if
消除不需要的绑定。
所以我的问题是:作为设计指南,C ++ 11中的所有(比如说,大多数)setter函数是否应该被编写为接受通用引用的函数模板?
除了在这些setter函数中编写代码时使用类似Intellisense的帮助工具的语法更加繁琐和不可能,假设原则“写入setter函数作为接受通用引用的函数模板时,是否存在任何相关的缺点可能“?
答案 0 :(得分:37)
您知道A类和B类,因此您知道它们是否可移动,以及最终是否需要此设计。对于类似std::string
的内容,除非您知道此处存在性能问题,否则更改现有代码会浪费时间。如果您正在处理auto_ptr
,则需要将其删除并使用unique_ptr
。
如果您不知道更具体的内容,通常首选按值 - 例如
void set_a(A a) { _a = std::move(a); }
这允许使用A
的任何构造函数,除了可移动性之外不需要任何东西,并提供相对直观的界面。