C++ 何时使用 const 引用而不是转发引用
C++ When to use const Reference over Forwarding Reference
假设我们需要使用模板化参数 T t
实现一个函数 f
。该函数不应复制 t
并接受 rvalues
和 lvalues
,因此有两种实现方式:
template <class T>
void f(const T& t) { ... }
template <class T>
void f(T&& t) { ... }
如果我们想改变f
里面的t
或者需要保留值类别,我们必须使用第二个版本。那么按照这种思路,我们什么时候以及为什么会选择第一个选项?
在这种一般情况下,没有理由同时编写两个重载。
如果 f
只观察它的参数,那么只需要 const T&
重载。
如果 f
只是将其参数转发给其他函数,则只需要 T&&
重载,并将使用 std::forward<T>
。 (这包括函数需要保留值副本的情况,即, 将其转发给 copy/move 构造函数。)
当您想向函数的客户提供强有力的保证 t
不会在 f
内部更改时,您将主要选择第一个选项。尽管您可以删除 const
限定符并且仍然不修改 t
,但如果您不更改它,则将其限定为 const
参数被认为是良好的实践和良好的界面设计它被称为内部值一个函数,加上它可以帮助编译器更好地优化代码。
另外,知道你可以使用 const_cast
来绕过 const
的类型安全,如果你真的必须的话,但请记住你正在做的就是:摆脱类型安全。不惜一切代价避免这种情况。
最后,const
限定符不会阻止复制,您可以轻松地执行以下操作:
int main()
{
const int a = 3;
int b = a; // a is copied to b
}
假设我们需要使用模板化参数 T t
实现一个函数 f
。该函数不应复制 t
并接受 rvalues
和 lvalues
,因此有两种实现方式:
template <class T>
void f(const T& t) { ... }
template <class T>
void f(T&& t) { ... }
如果我们想改变f
里面的t
或者需要保留值类别,我们必须使用第二个版本。那么按照这种思路,我们什么时候以及为什么会选择第一个选项?
在这种一般情况下,没有理由同时编写两个重载。
如果 f
只观察它的参数,那么只需要 const T&
重载。
如果 f
只是将其参数转发给其他函数,则只需要 T&&
重载,并将使用 std::forward<T>
。 (这包括函数需要保留值副本的情况,即, 将其转发给 copy/move 构造函数。)
当您想向函数的客户提供强有力的保证 t
不会在 f
内部更改时,您将主要选择第一个选项。尽管您可以删除 const
限定符并且仍然不修改 t
,但如果您不更改它,则将其限定为 const
参数被认为是良好的实践和良好的界面设计它被称为内部值一个函数,加上它可以帮助编译器更好地优化代码。
另外,知道你可以使用 const_cast
来绕过 const
的类型安全,如果你真的必须的话,但请记住你正在做的就是:摆脱类型安全。不惜一切代价避免这种情况。
最后,const
限定符不会阻止复制,您可以轻松地执行以下操作:
int main()
{
const int a = 3;
int b = a; // a is copied to b
}