万能引用

右值引用用&&符号表示。右值引用主要是绑定到右值上,如:

int &&rv = 100;

看下面函数定义:

void myfunc(int &&tmprv) {
    cout << tmprv << endl;
    return;
}

int main() {
    myfunc(10); // 正确,右值作为实参
    int i = 100;
    myfunc(i); // 错误,右值引用不能接受左值
}

由此可知,右值引用肯定不能接受左值,现在将myfunc()函数改造成函数模板:

template<typename T>
void myfunc(T&& tmprv) {
    cout << tmprv << endl;
    return;
}

如果上面的T是int类型,那么函数myfunc()用int实例化后得到的函数似乎和普通的myfun()函数是一样的,但myfunc(i);并没有报错,因此推断T没有推断为int类型。

1. 万能引用

万能引用又称未定义引用,这种引用离不开两种语境:

  • 必须是函数模板;
  • 必须是发生了模板类型推断并且函数模板形参如T&&;

万能引用的格式如T&&,auto && tmpvalue = ...也是一个万能引用,其它的&&情况都是右值引用。

2. 万能引用资格的剥夺与辨认

剥夺:

const修饰词(前后)会剥夺一个引用成为万能引用的资格,被打回原型成为右值引用。

template<typename T>
void myfunc(const T&& tmprv) { // 有const存在,为右值引用
    cout << tmprv << endl; 
    return;
}

int main() {
    int i = 100;
    myfunc(i); // fault
}

辨认:

增加mytest类模板定义:

template<typename T>
class mytest{
pubic:
    void testfunc(T&& x) {} // 这不是万能引用,是右值引用
}

int main() {
    mytest<int> mc;
    int i = 100;
    mc.testfunc(i); // fault,左值不能绑定在右值引用上
}

为什么testfunc后面的T&&不是万能引用,而是一个右值引用,因为testfunc()成员函数本身并没有涉及类型推断,testfunc()成员函数是类模板mytest的一部分,首先得用以下语句实例化这个类模板的一个具体类:

mytest<int> mc;

实例完这个类之后,mytest<int>类存在了,那么testfunc()成员函数才真正存在,所以testfunc()成员函数存在的时候就已经为:

void testfunc(int&& x) {}

所以testfunc()函数本身没有涉及类型推断,这个x是右值引用。如果增加一个public修饰的成员函数模板:

template<typename T>
class mytestc {
public:
    void testfunc(T&& x) {} // 右值引用
    
    template<typename T2>
    void testfunc2(T2&& x) {} // 万能引用
};

int main() {
    mytestc<int> myoc;
    int i = 10;
    myoc.testfunc2(i); // 左值可以,右值10也可以
}

 

posted @   小熊酱  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示