首页 > 编程语言 >Effective Modern C++(一)

Effective Modern C++(一)

时间:2023-06-03 17:33:40浏览次数:34  
标签:推导 Effective 右值 Modern C++ vector 引用 && 类型

通用引用与右值引用

  我们以T&&的形式声明一个右值引用,但并不是所有形如T&&形式的声明都为右值引用,他还有可能是一个万能引用。

  事实上,“T&&”有两种不同的意思。第一种,当然是右值引用。这种引用表现得正如你所期待的那样:它们只绑定到右值上,并且它们主要的存在原因就是为了识别可以移动操作的对象。

T&&”的另一种意思是,它既可以是右值引用,也可以是左值引用。这种引用在源码里看起来像右值引用(即“T&&”),但是它们可以表现得像是左值引用(即“T&”)。它们的二重性使它们既可以绑定到右值上(就像右值引用),也可以绑定到左值上(就像左值引用)。 形如万能引用的声明需要在对其初始化时才能确定是一个左值引用还是一个右值引用(类似多态?)。

  在两种情况下会出现通用引用。最常见的一种是函数模板形参

template < typename T>
void func(T&& param);

  第二种情况是auto声明符,因为auto的底层机制就是利用模版推导来推导变量类型的

auto&& var2 = var1;                 //var2是一个通用引用

  这两种情况的共同之处就是都存在类型推导type deduction

  对一个通用引用而言,类型推导是必要的,但是它还不够。引用声明的形式必须正确,并且该形式是被限制的。它必须恰好为“T&&

template <typename T>
void f(std::vector<T>&& param);     //param是一个右值引用

  比如以上的param类型声明就不是一个通用引用,因为它的类型是std::vector<T>&& 而不是T&&,所以他是一个右值引用。同样的一个const修饰符也会让它失去成为通用引用的资格。

 

  现在,让我们来总结一下成为通用类型的必要条件:

  1. 变量的类型需要被类型推导,这往往出现在模版内的。
  2. 必须严格遵循形如T&&的格式。

  但值得注意的是,模版内的形如T&&的引用不一定是万能引用,因为他有可能不发生类型推导!(这就是c++,总是存在着各种例外)

  

template<class T, class Allocator = allocator<T>>   //来自C++标准
class vector
{
public:
    void push_back(T&& x);
    …
}

  我们要想判断T&& x是否是一个通用引用,需要先判断它是否需要类型推导,它需要吗?

  让我们想想何时需要调用这个方法,很显然,当我们先有了一个实例,才能调用这个方法。而当我们有了实例,T的类型就已经确定了,这时候再调用push_back就不存在类型推导了。、

  比如当我们将vector声明为std::vector<Widget>时,模版将被实例化为以下代码

class vector<Widget, allocator<Widget>> {
public:
    void push_back(Widget&& x);             //右值引用
    …
};

  但这并不代表所有相似的成员函数都不存在类型推导,比如

template<class T, class Allocator = allocator<T>>   //依旧来自C++标准
class vector {
public:
    template <class... Args>
    void emplace_back(Args&&... args);
    …
};

  这里类型参数(type parameterArgs是独立于vector的类型参数T的,所以Args会在每次emplace_back被调用的时候被推导。

最后

请记住:

  • 如果一个函数模板形参的类型为T&&,并且T需要被推导得知,或者如果一个对象被声明为auto&&,这个形参或者对象就是一个通用引用。
  • 如果类型声明的形式不是标准的type&&,或者如果类型推导没有发生,那么type&&代表一个右值引用。
  • 通用引用,如果它被右值初始化,就会对应地成为右值引用;如果它被左值初始化,就会成为左值引用。

 

标签:推导,Effective,右值,Modern,C++,vector,引用,&&,类型
From: https://www.cnblogs.com/icecreamjn/p/17454289.html

相关文章

  • 6.3测试题以及参考答案(C++基础)
    测试题总分120,时间180分钟一、单选题(每题2分,共40分)C++中表示大于等于用以下哪个关系运算符(B)A.>B.>=C.≥D.>&=C++中,不等于用以下哪个关系运算符(C)A.<>B.≠C.!=D.==表达式7%2的值是多少(B)A.0B.1C.2D.-1要计算变量B的......
  • 理解C++底层细节
    理解C++底层细节C++是一门广泛使用的高级编程语言,其语法优雅且易于使用,拥有着强大的面向对象特性以及丰富的标准库。但是,在理解C++的本质之前,我们需要先了解C++的底层细节。C++中的内存管理在C++中,内存管理和分配是至关重要的内容。常见的内存管理问题包括内存泄漏、内存溢出和野指......
  • 1. C++编程简介
    勿在浮沙筑高台课程:C++面向对象程序设计。面向对象,它是一个观念。那么我们要用这种观念来写程序,需要面向对象的语言,而C++就是一个支持面向对象观念的一种语言。上这门课你该具备什么样的基础呢?只要你有这些基础就够了,你曾经学过某一种procedurelanguage,最好是C语言,但是......
  • Visual C++ 6.0环境开发PACS影像系统的技术指标和精准算法
    1.技术指标图像文件格式:DCM、JPG、BMP、TIF等可支持显示属性设置:24/32位真彩;256位色(黑白)可支持监视器分辨率:1024﹡768;1280﹡1024;1600﹡1280;1280﹡1600(立式);1536﹡2048(立式);2560﹡2048(立式)图像分辨率:1024﹡1024;512﹡512;256﹡256静态或动态操作平台windowsxpPACS系统-图像处理高级精准算法对图像......
  • C++面向对象
    文章目录C++类&对象C++类定义定义C++对象访问数据成员类&对象\详解类成员函数类访问修饰符构造函数&析构函数C++拷贝构造函数C++友元函数C++内联函数C++中的this指针C++中指向类的指针C++类的静态成员继承基类&派生类访问控制和集成继承类型多继承继承顺序重载运算符和重载函数C++......
  • C++逆向分析——构造函数和析构函数
    构造函数与析构函数构造函数structStudent{inta;intb;Student(){printf("Look.");}voidInit(inta,intb){this->a=a;this->b=b;}};如上代码中,我们发现了存在一个函数,这个函数没有返回类型并且与结构体名称一样,那这段函数在什么时候执......
  • Mac在VSCode中搭建CC++环境
    Mac在VSCode中搭建C/C++环境https://www.jianshu.com/p/050fa455bc74利用VScode和cmake编译构建C++工程代码https://m.oldpan.me/archives/use-vscode-cmake-tools-build-projectVSCode开发C在Mac的配置https://www.jianshu.com/p/014e6e2c97e2选择C/Cpp:EditConfiguration......
  • 2016第七届蓝桥杯国赛决赛c/c++本科B组试题总结及解题答案
    未完待更新........1.一步之遥从昏迷中醒来,小明发现自己被关在X星球的废矿车里。矿车停在平直的废弃的轨道上。他的面前是两个按钮,分别写着“F”和“B”。小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。按F,会前进97米。按B会后退127米。 透过昏暗的灯光,小明看......
  • C++字符串分割和C语言常用格式控制
    C++string的输出格式控制输出一个字符串:左对齐,字宽为10,空格填充1.strings;2.cin>>s;3.cout<<std::left<<setw(10)<<setfill('*')<<s<<endl;输入:love输出效果:love******C++string字符流字符分割技巧输入一行字符串,然后按某个字符分割成若干子串1.strings;......
  • c++ libcurl获取http header信息
    boolHttpDownloader::GetReceiveHeaderInfo(conststd::string&strUrl,std::map<std::string,std::string>&mapHeaderKeyValue){boolbRet=false;if(strUrl.empty()){returnbRet;}else{CURL*handl......