有关c++11的一些特性

很久都没进来了,感觉最近很疲惫,今天我i什么要学这个东西呢,是因为自己被不同的人问了很多次,好歹自己也学过c++;被人问过却不知道c++11真的觉得很丢人,所以我这个菜鸟打算了解一下(虽然只是皮毛),这也是分内之事喽,一起学习学习,看看人家的介绍,自己想动手试一试(你也可以动动爪爪,哈哈),在看一本书叫《深入理解c++11》,大家可以瞅瞅大笑

一:c++11的诞生

2011年11月,c++11/c++0x标准被标准委员会批准通过,至此c++11标准尘埃落定。发展史就简单介绍啦,本人觉得如果c++98/03如果比作一辆奔驰宝马汽车的话,那么C++11就是兰博基尼或者法拉利(哈哈),因为它不仅兼容c++03/98,而且在此基础上做了大量缺点的改进,还有许多新功能的增加,各种配置都该是最佳的,尽管未来还会不会有更ai的c++语言,就目前而言,还是很特点鲜明的吧。

整体的设计目标:

//使c++成为更好的适用于系统开发及库开发的语言(感觉c++的地位好像不如从前了难过

//使得c++成为更容易教学的语言(语法更加一致化和简单化)

//保证语言的稳定性,以及c++03及c语言的兼容性

二:c++11的一些新特性

<1>c++11引入的新的关键字:

alignas

alignof decltype

auto(重新定义)

static_assert

using(重新定义)

noexcept

nullptr

constexpr

thread_local

<2>倾向于使用语言来实现特性库而不是扩展

<3>更倾向于通用的而不是特殊的手段来实现特性

eg :c++98中类型转化操作符可以参与隐式转化,而有时我们只是希望在显式时再发生转化

<4>不再是专家才能操纵的语言(菜鸟也可以偷笑

eg:c++11采用最长匹配的解析规则

这是我用vs2012写的


这是我用dev写的(比较老,当时傻的还不知道为什么不对)


但是如果这样写就是对的:


<5>增强类型的安全性

c++11标准引入了“强类型枚举”;在c++98/03枚举会退化成整形,会与其他的枚举类型混淆,C++11则有修正

dev下:


dev也不行,vs2012支持c++11,肯定也不行


<6>与硬件紧密合作

c++11引入原子型,保证线程正确同步,为开发者和系统建立一个高效的同步机制

三:c++11的兼容性和稳定性

<1>保持与c++99兼容

1:_func_ 预定义标识符(vs里面我查了一下叫FUNCTION,我也不是很清楚啦哈哈)


2:pragma 操作符

保证头文件不被重复包含

#pragma once 等同于

#ifndef _x_H

#define _x_H

3:静态断言:


这就保证了指针不为null且数组的为有效数组了

c++11引入了static_assert:,使得错误更加容易找到,原因是assert是运行时的断言,而static_assert是编译时期的断言

传入两个参数,一个参数传入的是你要断言的表达式(常量Bool值),一个传入的警告信息(一个字符串)


这样就很容易知道错误在哪里了。。。。

4:long long 类型(至少64位)


5:快速初始化类成员变量

我们可以看出在dev里面写的,发现成员c可以就地初始,在vs里面却不行好奇怪,不知道为什么,不过可以肯定的是c++11是支持成员变量可以不通过初始化列表初始化成员变量,可以就地初始化

而且c++11还支持花括号赋初始值;类似于这样: struct Init{ int a = 0;double b {5.5}; };//就不做演示了。

6:外部模板

外部模板是c++11中关于模板性能上的一个改进。

我们在test.h的文件中声明了这样一个模板函数:tempate <typename T> void fun(T){}

在第一个test1.cpp文件中,我们定义了这样一行代码:

#include "test.h"

void test(){fun(3);}

在另一个test2.cpp文件中,我们也定义了这样一些代码

#include "test.h"

void test(){fun(3);}

由于两个源代码使用的模板函数参数类型一致,所以在编译test1.cpp的时候,编译器实例化出了fun<int>(int),而当编译test2.cpp的时候,编译器又在一次实例化出了函数fun<int>(int),这样,在test1.o和test2.o目标文件中,会有两份一摸一样的函数fun<int>(int),代码重复,在链接的时候,连接器通过一些编译器辅助的手段将重复的模板函数代码fun<int>(int)删除掉,只保留单一个副本,这样一来,就解决了模板实例化时产生的代码冗余问题,但是,如果这样的相同代码多了,会极大的增加编译器的便宜时间和链接时间,怎样解决呢,哈哈,当然就是c++11新引入的外部模板喽

外部模板的使用依赖于显示实例化:类似于这样::

template<typename T> void fun(T){}

我们只需要这样声明一下:template void fun<int>(int);这就可以使得编译器在本编译器单元中实例化出一个fun<int>(int)版本的函数(强制实例化),而在c++11中,又加了外部模板的声明,外部模板的声明根显示的实例化差不多,加了一个关键字extern,大家应该并不陌生,对于上面的例子,我们可以这样做:extern template void fun<int>(int);

///

所以,对于上面的例子,我们可以这样修改:

我们首先在test1.cpp做显示的实例化:

#include "test.h"

template void fun<int>(int);//显示实例化

void test1(){fun(3);}

然后我们在test2.cpp中做外部模板的声明

#include "test.h"

template void fun<int>(int);//显示实例化

void test2(){fun(3);}

这样的话,在test2.o中不会再生成fun<int>(int)的实例化代码,因此在链接的时候,应该要比较轻松了吧。但是外部模板不能用于静态函数(local)

三:通用才是硬道理

1:右值引用:移动语句和完美转发

移动语句:对于我的理解就是将资源从一个对象拷贝到另一个对象的时候,不需要临时对象的创建,拷贝及销毁,能够大幅度提高c++程序的功能,它是将这些资源从一个对象转移到另一个对象。在别的资料看到这样一段话,感觉很形象,他说类比文件的剪切和拷贝,当我们将文件从一个目录拷贝到另一个目录时,速度要比剪切慢很多。

在c++中,我们可以定义移动拷贝构造函数和移动赋值函数

一般而言,当我们用临时对象拷贝构造新对象的时候,会在函数返回的时候产生临时对象,作为函数的返回值,而这个临时量会构造主函数的新对象,这样一来,调用两次构造函数,而c++11的做法是在临时对象构造a的时候不分配内存,让新对象的成员变量指向临时对象的堆内存资源,同时保证临时对象不释放所指向的堆内存,在构造完成后,临时对象被析构,新对象就偷走了临时对象所拥有的堆内存资源。(不过我们老师教的是直接调用构造函数,不产生临时量,谁能给我解释下难过,我还试了一下)


意思是将临时对象直接初始化了新对象的d,在放入新对象的内存中,不在调用拷贝构造函数。。。。。。

移动构造函数接收右值引用参数


左值引用接收左值,右值引用接收右值

int x = 0;

int &a = x;//左值引用

int &&a = 10;//右值引用

#include <utility>

std::move()函数强制一个左值成为右值,等同于一个类型转换:

static_cast<T&&>(lvalue)


这个比较经典,没有资源的申请释放,只是在移动资源。

完美转发,感觉其实就是对函数的一种包装,看起来比较统一整齐规范化,大家可以看看这个例子(自己也可以动动手,哈哈)

脑子好疼,就先写到这里,呼,后续在学习吧,哈哈,眼睛快睁不开了---------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值