位置: 编程技术 - 正文

c++11深入学习(c++11视频教程)

编辑:rootadmin

推荐整理分享c++11深入学习(c++11视频教程),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:c++11using,c++深入理解,c++11教程在线教程,c++深入理解,c++学完基础怎么深化,c++11教程,c++11教程,深入c++11应用 pdf,内容如对您有帮助,希望把文章链接给更多的朋友!

委托构造函数

在引入C&#;&#; 之前,如果某个类有多个重载的构造函数,且这些构造函数中有一些共同的初始化逻辑,通常都需要再编写一个带参数的初始化函数,然后在这些构造函数中调用这个初始化函数。在C&#;&#; 中,再也不用这么麻烦了。我们可以实现一个最基础的构造函数,其他构造函数都调用这个构造函数。示例代码如下:

1 class CPerson

2 {

3 public:

4 CPerson() : CPerson(0, "") { NULL; }

5 CPerson(int nAge) : CPerson(nAge, "") { NULL; }

6 CPerson(int nAge, const string &strName)

7 {

8 stringstream ss;

9 ss << strName << "is " << nAge << "years old.";

m_strInfo = ss.str();

}

private:

string m_strInfo;

};

统一的初始化语法

在引入C&#;&#; 之前,有各种不同的初始化语法。在C&#;&#; 中,仍可以使用这些初始化语法,但也可以选择使用新引入的统一的初始化语法。统一的初始化语法用一对大括号{}表示,使用{}初始化语法还可有效地避免窄转换。示例代码如下:

1 int a{5};

2 char c{'X'};

3 int p[5] = {1, 2,3, 4, 5};

4 vector<int> vctTemp{1, 2, 3};

5 CPerson person{, "Mike"};

6 int b = 5.3; // b赋&#;成5,发生了窄转换

7 int d{5.3}; // 会提示编译错误,避免了窄转换

语法甜点4:nullptr

nullptr是C&#;&#; 中新加的一个关键字,用于标识空指针。引入nullptr后,可以解决某些函数重载时的二义性问题。示例代码如下:

1 void F(int a)

2 {

3 cout << a << endl;

4 }

5

6 void F(char *p)

7 {

8 assert(p != NULL);

9

cout << p << endl;

}

int main(int argc, _TCHAR* argv[])

{

int *p = nullptr;

int *q = NULL;

bool bEqual = (p == q); // 两个指针&#;是相等的,bEqual为true

int a = nullptr; // 编译失败,nullptr不是转换为int

F(0); // 在C&#;&#; 中编译失败,有二义性;在C&#;&#; 中调用F(int)

F(nullptr); // 调用F(char *)

getchar();

return 0;

}

成员变量初始化

与Java和C#中的用法一样,可以对成员变量进行就地初始化。示例代码如下:

1 class CPerson

2 {

3 private:

4 int m_nAge = ;

5 string m_strName = "Mike";

6 };

默认或禁用函数

当我们定义了自己的带参数的构造函数时,编译器将不再生成默认的构造函数,如果此时想使用默认的构造函数,则必须显式地声明并定义不带参数的构造函数。在C&#;&#; 中,我们可以使用default关键字来表明我们希望使用默认的构造函数。类&#;的,当我们不想外部使用编译器自动生成的构造函数或赋&#;函数时,我们一般需要将其声明成protected或private的。在C&#;&#; 中,我们可以使用delete关键字来表明我们不希望编译器生成默认的构造函数或赋&#;函数。示例代码如下:

1 class CPerson

2 {

3 public:

4 CPerson() = default;

5 CPerson(const CPerson &person) = delete;

6 };

static_assert

静态断言static_assert由一个常量表达式和一个字符串构成。在编译期间,将计算常量表达式的&#;,如果为false,字符串将作为错误信息输出。示例代码如下:

1 char a = ;

2 static_assert(sizeof(a)==4, "a is not an integer.");

模板右边双括号

在C&#;&#; 中,vector<vector<int>> vctTemp是一个非法的表达式,编译器会认为右边的>>是一个移位操作符,因此必须修改为vector<vector<int> > vctTemp,即在右边的两个>中间添加一个空&#;。在C&#;&#; 中,这将不再是一个问题,编译器将能够识别出右边的双括号是两个模板参数列表的结

-

继承的构造函数

当一个派生类的某个函数隐藏了基类中的某个同名函数时,如果我们想在派生类中导出基类中的这个同名函数,可以通过using Base::Func的方式将基类中的这个同名函数引入到派生类的作用域内。当该方法只对普通成员函数有效,不能用于构造函数。在C&#;&#; 中,如果派生类认为基类的构造函数已经足够,则也可以使用using Base::Base的方式将基类的构造函数引入到派生类的作用域内。但需要注意的是,此时派生类中的成员变量并没有进行初始化,所以应当对这些成员变量进行就地初始化。示例代码如下:

1 class CBase

2 {

3 };

4

5 class CDerived : public CBase

6 {

7 public:

8 using CBase::CBase;

9 CDerived(int nData) : m_nData(nData) { NULL; }

private:

int m_nData = ;

};

初始化列表

在引入C&#;&#; 之前,只有数组能使用初始化列表。在C&#;&#; 中,vector、list等各种容器以及string都可以使用初始化列表了。初始化列表对应的类为initializer_list,vector、list等各种容器以及string之所以可以使用初始化列表,是因为它们重载了参数类型为initializer_list的构造函数(称为初始化列表构造函数)和赋&#;函数(称为初始化列表赋&#;函数)。下面是一些使用初始化列表的例子。

1 void Print(const initializer_list<int> &ilData)

2 {

3 for (auto a : ilData)

4 {

5 cout << a << endl;

6 }

7 }

8

9 int main(int argc, _TCHAR* argv[])

{

vector<int> vctNum = {1, 2, 3, 4, 5};

map<string, string> mapID2Name = {{"", "Jack"}, {"", "Mike"}};

string strText{"hello world"};

Print({});

Print({1, 2});

Print({1, 2, 3, 4, 5});

getchar();

return 0;

}

非成员的begin和end

在C&#;&#; 中,标准容器都提供了begin和end成员函数,但对于普通数组,则只能使用不同的写法。比如:

1 vector<int> v;

2 int a[];

3 sort(v.begin(), v.end());

4 sort(a, a&#;sizeof(a)/sizeof(a[0]));

为了统一语法,C&#;&#; 提供了非成员的begin和end函数。用法如下:

1 sort(begin(v), end(v));

2 sort(begin(a), end(a));

显式虚函数重载

在引入C&#;&#; 之前,基类和派生类中的虚函数很容易产生错误使用的情况。比如:

a、基类添加了一个虚函数,但该虚函数与派生类中的某个已有普通函数相同。

b、派生类添加了一个普通函数,但该函数与基类中的某个已有虚函数相同。

为了避免这些情况,在C&#;&#; 中可以使用override来显式地表明需要进行虚函数重载。比如:

1 class Base

2 {

3 virtual void some_func(float);

4 };

5

6 class Derived : public Base

7 {

8 virtual void some_func(int) override; // 将产生编译错误

9 virtual void some_func(float) override; // 正确

};

C&#;&#; 中还引入了final指示符,用于防止类或接口被继承。比如:

1 class Base1 final { };

2 class Derived1 : public Base1 { }; // 将产生编译错误

3 class Base2

4 {

5 virtual void f() final;

6 };

7 class Derived2 : public Base2

8 {

9 void f(); // 将产生编译错误

};

C&#;&#; 中,可以使用typedef给模板类指定一个新的类型名称,但却不能给类模板指定别名。比如:

1 template< typename first, typename second, int third>

2 class SomeType; template< typename second>

3 typedef SomeType<OtherType, second, 5> TypedefName; // 在C&#;&#; 中是不合法的

c++11深入学习(c++11视频教程)

无限制的union

在C&#;&#; 中,并非任意的数据类型都能做为union的成员。比方说,带有non-trivial构造函数的类型就不能是 union 的成员。在C&#;&#; 中,移除了所有对union的使用限制,除了其成员仍然不能是引用类型这种情况。

1 struct point

2 {

3 point() {}

4 point(int x, int y): m_x(x), m_y(y) {}

5 int m_x, m_y;

6 };

7 union

8 {

9 int z;

double w;

point p; // 在C&#;&#; 中不合法;在C&#;&#; 中合法

};

在C&#;&#; 中,允许sizeof运算符作用在类型的数据成员上,而无须明确的对象。在C&#;&#; 中,这是不允许的,会导致编译错误。比如:

1 struct SomeType { OtherType member; };

2 sizeof(SomeType::member); // 在C&#;&#; 中不合法;在C&#;&#; 中合法

新的算法

C&#;&#; 中新增了一些比较实用的算法。比如all_of、any_of、none_of、copy_n、copy_if和iota等。参考代码如下:

1 int a[5] = {-2, -1, 0, 1, 2};

2 auto funIsPositive = [](int v){return v>0;};

3 bool bRet = all_of(a, a&#;5, funIsPositive); // false

4 bRet = any_of(a, a&#;5, funIsPositive); // true

5 bRet = none_of(a, a&#;5, funIsPositive); // false

6 int b[5] = {0};

7 copy_n(a, 5, b); // 将a开始的5个元素拷贝到b中

8 copy_if(a, a&#;5, b, funIsPositive); // 将1, 2两个数拷贝到b中

9 iota(a, a&#;5, ); // a中的每个元素加

泛化的常数表达式

C&#;&#; 中本来就已经具有常数表示式的概念,比如:3&#;5,6*7等。常数表示式对编译器来说是优化的机会,编译器常在编译期运行它们并且将&#;存入程序中。同样地,在许多场合下,C&#;&#;规范要求使用常数表示式。比如数组大小、枚举&#;等。

然而,常数表示式总是在遇到了函数调用时就终结。比如:

1 int GetFive() { return 5; }

2 int some_value[GetFive() &#; 5]; // 不合法

C&#;&#; 引进关键字constexpr允许用户保证函数是编译期常数。比如:

1 constexpr int GetFive() { return 5; }

2 int some_value[GetFive() &#; 5];

C&#;&#; 中引入的一个非常重要也是比较难于理解的新特性就是完美转发(Perfect Forwarding)。完美转发中有两个关键词:“转发”和“完美”。

我们先来看第一个关键词“转发”,那么在C&#;&#;中,“转发”表示什么含义呢?转发通常用在模板编程中,假设有一个函数F(a1, a2, ..., an),如果存在另一个函数G(a1, a2, ..., an),调用G相当于调用了F,则我们说函数G将a1, a2, ..., an等参数正确地转发给了函数F。再来看第二个关键词“完美”,“完美”转发是相对于其他转发方案而言的。在目前已提出的7种转发方案中,只有完美转发能够正确地实现转发的语义,其他方案都存在这样或那样的问题。下面一一进行介绍。

转发方案一:使用非常量左&#;引用。考虑下面的代码。

1 void F(int a)

2 {

3 cout << a << endl;

4 }

5

6 template<class A>

7 void G(A &a)

8 {

9 F(a);

}

使用非常量左&#;引用时,我们可以调用F(),但无法调用G(),即我们无法接收非常量右&#;的参数。

转发方案二:使用常量左&#;引用。考虑下面的代码。

1 void F(int &a)

2 {

3 cout << a << endl;

4 }

5

6 template<class A>

7 void G(const A &a)

8 {

9 F(a);

}

使用常量左&#;引用时,函数G可以接收任意类型的&#;作为参数,包括非常量左&#;、常量左&#;、非常量右&#;和常量右&#;。但当F的参数类型为非常量左&#;引用时,我们无法将一个常量左&#;引用转发给一个非常量左&#;引用。

转发方案三:使用非常量左&#;引用 &#; 常量左&#;引用。考虑下面的代码。

1 template<class A>

2 void G(A &a)

3 {

4 F(a);

5 }

6

7 template<class A>

8 void G(const A &a)

9 {

F(a);

}

综合前面两种方案的分析结果,可以得出这种方案相当于对函数G进行了重载,此时可以接收任意类型的&#;作为参数,也可以顺利地实现转发。但由于使用了常量和非常量两种形式的重载,当参数的个数N较大时,需要重载的函数会呈指数级增长(2的N次方),因此这种方案实际上是不可取的。

转发方案四:使用常量左&#;引用 &#; const_cast。

1 template<class A>

2 void G(const A &a)

3 {

4 F(const_cast<A &>(a));

5 }

这种方案克服了方案二的缺点,现在可以将常量左&#;引用转发给非常量左&#;引用了。但这又带来了新的问题,假如F的参数是一个非常量左&#;引用,则调用G后,我们可以通过F来修改传入的常量左&#;和常量右&#;了,而这是非常危险的。

转发方案五:非常量左&#;引用 &#; 修改的参数推导规则。

这种方案与方案一类&#;,但需要修改现有的参数推导规则,即传递一个非常量右&#;给模板类型时,将它推导成常量右&#;,这样就解决了方案一中无法接收非常量右&#;的参数的问题。但由于修改了现有的参数推导规则,因此会导致已有代码的语义发生改变。考虑下面的代码。

1 template<class A>

2 void F(A &a)

3 {

4 cout << "void F(A& a)" << endl;

5 }

6

7 void F(const long &a)

8 {

9 cout << "void F(const long &a)" << endl;

}

在未修改参数推导规则前,调用F()会选择第二个重载函数,但修改后,却会调用第一个重载函数,这就给C&#;&#;带来了兼容性的问题。

转发方案六:右&#;引用。考虑下面的代码。

1 template<class A>

2 void G(A &&a)

3 {

4 F(a);

5 }

在这种方案中,G将无法接收左&#;,因为不能将一个左&#;传递给一个右&#;引用。另外,当传递非常量右&#;时也会存在问题,因为此时a本身是一个左&#;,这样当F的参数是一个非常量左&#;引用时,我们就可以来修改传入的非常量右&#;了。

转发方案七:右&#;引用 &#; 修改的参数推导规则。

要理解修改后的参数推导规则,我们先来看一下引用叠加规则:

1、T& &#; & = T&

2、T& &#; && = T&

3、T&& &#; & = T&

4、T或T&& &#; && = T&&

修改后的针对右&#;引用的参数推导规则为:若函数模板的模板参数为A,模板函数的形参为A&&,则可分为两种情况讨论:

1、若实参为T&,则模板参数A应被推导为引用类型T&。(由引用叠加规则第2点T& &#; && = T&和A&&=T&,可得出A=T&)

2、若实参为T&&,则模板参数A应被推导为非引用类型T。(由引用叠加规则第4点T或T&& &#; && = T&&和A&&=T&&,可得出A=T或T&&,强制规定A=T)

应用了新的参数推导规则后,考虑下面的代码。

1 template<class A>

2 void G(A &&a)

3 {

4 F(static_cast<A &&>(a));

5 }

当传给G一个左&#;(类型为T)时,由于模板是一个引用类型,因此它被隐式装换为左&#;引用类型T&,根据推导规则1,模板参数A被推导为T&。这样,在G内部调用F(static_cast<A &&>(a))时,static_cast<A &&>(a)等同于static_cast<T& &&>(a),根据引用叠加规则第2点,即为static_cast<T&>(a),这样转发给F的还是一个左&#;。

当传给G一个右&#;(类型为T)时,由于模板是一个引用类型,因此它被隐式装换为右&#;引用类型T&&,根据推导规则2,模板参数A被推导为T。这样,在G内部调用F(static_cast<A &&>(a))时,static_cast<A &&>(a)等同于static_cast<T&&>(a),这样转发给F的还是一个右&#;(不具名右&#;引用是右&#;)。

可见,使用该方案后,左&#;和右&#;都能正确地进行转发,并且不会带来其他问题。另外,C&#;&#; 为了方便转发的实现,提供了一个函数模板forward,用于参数的完美转发。使用forward后的代码可简化为:

1 template<class A>

2 void G(A &&a)

3 {

4 F(forward<A>(a));

5 }

为了便于进行各种转发方案的比较,下面以表&#;的形式列出了各自的特性。

转发方案非常量左&#;常量左&#;非常量右&#;常量右&#;修改语言已知问题

一、非常量左&#;引用非常量左&#;常量左&#;无法转发常量左&#;否无法接收非常量右&#;的参数

二、常量左&#;引用常量左&#;常量左&#;常量左&#;常量左&#;否无法将常量左&#;引用转发给非常量左&#;引用

三、非常量左&#;引用 &#; 常量左&#;引用非常量左&#;常量左&#;常量左&#;常量左&#;否重载函数过多,实际编码不可行

四、常量左&#;引用 &#; const_cast非常量左&#;非常量左&#;非常量左&#;非常量左&#;否可修改常量左&#;和常量右&#;,不安全

五、非常量左&#;引用 &#; 修改的参数推导规则非常量左&#;常量左&#;常量左&#;常量左&#;是会导致兼容性问题,且不支持移动语义

六、右&#;引用无法转发无法转发非常量左&#;常量左&#;是可修改非常量右&#;,不安全

七、右&#;引用 &#; 修改的参数推导规则非常量左&#;常量左&#;非常量右&#;常量右&#;是暂无,故简称为完美转发

wode 下载 :

cocos2dx初学日记 CC_SYNTHESIZE(varType,varName,funName)这是一个自动生成been方法的宏,该方法可以为一个私有变量(假设是inta)设置get,set方法----CC_SYNTHESIZE(int,a,A);第三个参

[置顶] Cocos3.4 横版游戏制作-《KillBear》-添加地图 转载时请务必以超链接形式标明文章原始出处、作者信息和本声明。资源为网上寻找的,仅研究学习用,若是侵犯版权请通知本人整改。此篇为第一篇,我

Cocos2dx 3.0 lambda表达式的使用 本篇博客来自star特,转载请注明出处。

标签: c++11视频教程

本文链接地址:https://www.jiuchutong.com/biancheng/372773.html 转载请保留说明!

上一篇:Fast TileMap

下一篇:cocos2dx初学日记(cocos2dx4.0教程)

  • 税务稽查以前年度进项税额转出
  • 一般纳税人企业所得税多久申报一次
  • 企业给员工购买社保的规定
  • 职工的困难补助计入什么科目
  • 发票红冲需要做账吗
  • 公司废料收入如何分配
  • 小规模一直零申报也要工商申报吗?
  • 水果销售公司账务怎么做
  • 食品增值税专用发票可以退税吗?
  • 转增股本是不是缴个人所得税
  • 外商企业增资
  • 单位装修质保金扣留的会计处理
  • 税率变化递延所得税资产如何调整
  • 公司制度奖励怎么写
  • 免抵退税的账务处理
  • 出差出了事故怎么处理
  • 股权转让的违约条款
  • 一般纳税人贸易公司每个月最低费用多少
  • 电子发票能不能作废重开
  • 福利费申报个人所得税该如何进行?
  • 职工因公出差伙食补助标准
  • 不申报税务登记被注销
  • 销售的增长率公式是什么
  • 分支机构能否核定企业所得税
  • 车提折旧会计分录
  • 没有签订合同需要申报印花税吗
  • 收取赔偿金开具什么发票
  • 出口退税需要什么单据
  • 苹果哪些手机有120hz刷新率
  • 发生以前年度损益调整
  • win7为什么还有人用
  • 工资里的其他应收款是什么
  • 认证未抵扣的发票购买方能开红字信息表吗
  • 房地产评估费计算公式
  • 先出库还是先发货
  • 计算机视觉就业前景
  • 其他应付款怎么平账
  • 软件集成电路企业所得税优惠政策
  • Symfony2实现在controller中获取url的方法
  • php redis常用命令
  • php面向对象是什么意思
  • 分公司不享受小规模纳税
  • 企业财务准则最新
  • 金融企业会计科目有哪些
  • 金蝶怎么修改制单人
  • 外贸客户付款方式
  • 应交税费在借方怎么调平
  • 存货成本核算方法的多久变更
  • sql语句分组汇总
  • 个体工商户增值税怎么计算
  • 建筑劳务公司的会计账务处理
  • 长期待摊费用属于利润表项目吗
  • 固定资产折旧的影响因素
  • 经营地址怎么变更
  • 明细账建账的步骤
  • 工业企业营业税率
  • mysql几天能学会
  • sqlserver数据库备份
  • 安装solaris11
  • win1020h2版本怎么更新
  • win7系统打不开win10安装包
  • 删除同步中心图标
  • linux系统怎么添加用户名和密码
  • cocos2dx怎么安装
  • opengl裁剪平面
  • [置顶]游戏名:chivalry2
  • qt配置opengl
  • jquery插件怎么用到自己的网站
  • node.js中的http.response.writeHead方法使用说明
  • arp欺骗防护软件
  • elementui基于vue
  • jquery实例
  • 国家财政税务局
  • 收到虚开增值税专用发票怎么处理
  • 江苏省国家税务总局江苏省电子税务局
  • 企业医院和事业医院的区别
  • 顺丰快递的开票历史如何删除
  • 税务师事务所企业组织架构
  • 公车补贴计入工资吗
  • 中国古代的税收制度的演变
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设