首页 > 解决方案 > 我应该在我的代码中使用 `const T&` 而不是 `T&&` 像 stl

问题描述

我编写了如下代码:

template<bool B, typename IfT, typename ThenT>
using conditional_t = std::conditional_t<B, IfT, ThenT>;

template <bool B,
  typename IfT, typename ThenT>
constexpr auto conditional_v(IfT&& t1, ThenT&& t2)
  -> conditional_t<B, IfT, ThenT> {
  if constexpr (B) {
    return t1;
  } else {
    return t2;
  }
}

如果按值传递conditional_v<true>(0, 1),我们可以得到

template<>
inline constexpr conditional_t<true, int, int> conditional_v<true, int, int>(int && t1, int && t2)
{
  if constexpr(true) {
    return t1;
  }

}

如果通过引用传递conditional_v<true>(i, j),我们将得到

template<>
inline constexpr conditional_t<true, int &, int &> conditional_v<true, int &, int &>(int & t1, int & t2)
{
  if constexpr(true) {
    return t1;
  }

}

当我提到 stl 时,例如max

template< class T >
constexpr const T& max( const T& a, const T& b );

他们大多是通过const T&而不是T&&

所以我得到了一个问题:我应该const T&在我的情况下使用(就像 conditional_t,conditional_v 旨在在编译时选择一个初始值(int,文字字符串等......))。

标签: c++referencestl

解决方案


引入 T&& 是为了通过“窃取”传递的对象资源来避免不必要的副本。假设对象 rhs 有一个指向某个已分配资源 rhs.p 的指针,那么典型的用法是

void steal (T&& rhs){
  p=rhs.p;
  rhs.p=nullptr;
} 

由于在您的情况下std::max不打算更改参数,因此没有理由通过右值引用传递参数。此外,您将无法将其与左值引用一起使用。const T&除了命名变量之外,它还允许我们传递临时变量。例如

struct Test {};
Test returnObject(){
   Test t;
   return t;
}

int main(){
Test x;
Test& y=x;
Test&& z=x;//error cannot bind rvalue to lvalue
Test& r=returnObject();// error: cannot bind lvalue to rvalue
const Test& a=returnObject();// OK
Test&& b=returbObject();// OK
}

推荐阅读