C++笔记 - 通用引用

1,984 阅读1分钟

通用引用(universal reference) 是用来特指一种引用的类型。构成通用引用有两个条件:

  • 必须满足T&&这种形式

  • 类型T必须是通过推断得到的


下面看一个例子:

template <typename T>
class A {
	void func(T&& t) {}
}

上面的例子中func 函数的T&&不是通用引用。因为在类定义变量时,类型T就已经确定了,并不需要进行推断。如:A<int> a;


哪些情况下是通用引用呢:

  • 函数模板参数:

    #include <iostream>
    #include <type_traits>
    
    template <typename T> void print_reference_type(T &&i) {
        if (std::is_lvalue_reference<decltype(i)>::value) {
            std::cout << "lvalue: " << i << std::endl;
        } else if (std::is_rvalue_reference<decltype(i)>::value) {
            std::cout << "rvalue: " << i << std::endl;
        } else {
            std::cout << "unknown value: " << i << std::endl;
        }
    }
    
    int main(void) {
        int i = 0;
        print_reference_type(i);  // lvalue: 0
        print_reference_type(1); // rvalue: 1
    }
    

  • auto声明:

    #include <iostream>
    #include <type_traits>
    
    void print_reference_type(auto &&i) {
        if (std::is_lvalue_reference<decltype(i)>::value) {
            std::cout << "lvalue: " << i << std::endl;
        } else if (std::is_rvalue_reference<decltype(i)>::value) {
            std::cout << "rvalue: " << i << std::endl;
        } else {
            std::cout << "unknown value: " << i << std::endl;
        }
    }
    
    int main(void) {
        int i = 0;
        print_reference_type(i);  // lvalue: 0
        print_reference_type(1); // rvalue: 1
    }
    

那通用引用与其他引用有什么区别呢?最重要的区别是引用类型合成(Reference Collapsing Rules)。规则很简单:

  • T& & => T&
  • T&& & => T&
  • T& && => T&
  • T&& && => T&&

简单来说,就是传进来的如果是左值引用那就是左值引用,如果是右值引用那就是右值引用