位置: 编程技术 - 正文

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教程)

  • 收到政府的补贴收入现金流量表填哪里
  • 汽车购置税计算器2019
  • 计提住房公积金怎么算
  • 一般纳税人季报是哪几个月报税
  • 应收账款平均余额公式
  • 领备用金填什么单子
  • 合并报表成本法和权益法区别
  • 购买的二手车可以抵扣进项税额吗
  • 上年度的会计分录做错了今年可以调整吗
  • 委托加工模具的费用计入什么科目?
  • 网店会计的工作内容是什么
  • 出口退税进项发票
  • 没有业务来往可以报税吗
  • 申报状态显示申报失败
  • 滞留票的进项税能抵扣吗
  • 子公司与总公司的关系说明书
  • 公司向职工借款不还怎么办理
  • 合作方寄来的礼物能不能收?
  • 预付股权转让款如何处理
  • 在建工程可以质押吗
  • 用一般户发工资会怎么样
  • 收到转账支票又背书转让怎么写会计科目
  • App Store可以退款吗
  • 存货资产减值损失转回怎么做账
  • windows11怎么显示桌面图标
  • 增值税专用发票和普通发票的区别
  • 给员工支付的房租怎么算
  • CodeIgniter与PHP5.6的兼容问题
  • 写入缓存策略无法更改
  • uniapp vuecli
  • phpcms怎么用
  • 利润分配的账务处理如何做
  • php实现用户登录
  • load与initialize
  • 厂区绿化工程计入什么科目
  • 房地产企业土地出让金抵减销项税额
  • php trait用法
  • 小微企业免税额的会计分录
  • 职工报销医药费属于什么会计科目
  • 什么是半监督算法
  • pgadmin配置
  • mkisofs命令
  • 《中华人民共和国民法典》
  • 包装费和售后服务的区别
  • 网络购发票怎么读入
  • 还贷款的卡有利息吗
  • 一般公司是什么企业类型
  • 进项税额转出会影响当期纳税吗?
  • 预收账款发货
  • 织梦cms要钱吗
  • 季度所得税收入多报,年度可以调整吗
  • 奖金属于职工福利吗
  • mysql的常用命令
  • sqlserver验证方式
  • 养猪死亡
  • 应收账款核算流程
  • 单位收风险金违法吗
  • 软件产品销售合同范本
  • 企业成本核算项目以及成本核算流程
  • 小企业如何进行内部创新
  • 应收账款周转率高说明
  • 损益类科目没有结平是什么意思
  • 法人转移公司资产怎么办
  • 开红字发票如何做分录?
  • 工程设计费收入在所得税申报表应填入
  • 实缴资本和注册资本的比例
  • 原始凭证留存几年
  • sql not in 与not exists使用中的细微差别
  • mysql报错1091
  • 七喜r11c笔记本
  • mac的itunes怎么下载歌曲
  • cocos2dx node
  • Unity3D游戏开发标准教程吴亚峰于复兴人民邮电出版社
  • javascript+HTML5自定义元素播放焦点图动画
  • unity或者
  • js如何禁用按钮
  • qq个人资料显示王者战绩
  • 湖南省税务局网站2024公务员招聘
  • 深圳沙井社保局在哪个位置
  • 二手车中介公司怎么做账报税
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设