第三章 语言新特性

本文深入解析C++11的重要更新,包括nullptr、auto类型推导、一致性初始化、range-based for循环、move语义、noexcept关键字、constexpr、带别名的模板、lambda表达式及模板构造函数。同时,回顾基础类型初始化与main()定义规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、C++11语言新特性
1.微小但重要的语法提升

void f(int);
void f(void *);
f(0);//call f(int)
f(NULL);//call f(int) if NULL is 0
f(nullptr);//call f(void *) 

(1)nullptr是个新关键字。它被自动准换成各种pointer类型,但不会被准换成任何整数类型。
(2)nullptr的类型是nullptr_t,定义于
(3)nullptr_t是一个基础类型
2.以auto完成自动类型推导
(1)以auto声明的变量,其类型是会根据其初始值被自动推导出来,因此一定需要一个初始化操作

auto i;//ERROR:can't deduce the type of i

3.一致性初始化与初值列
(1)初始化可因为小括号、大括号或赋值操作符的出现而发生
(2)C++11引入了“一致性初始化”概念,即面对任何初始化动作,可以使用相同语法。也就是使用大括号:

int values[]{1,2,3};
std::vector<int>v{2,3,5,7,11,13,17};
std::vector<std::string>cities{
"Berlin","New York","London","Braunschweig","BeiJing"
};
std::complex<double>c{4.0,3.0};

(3)初值列会强迫造成所谓的value initialization。意思是:即使某个local变量属于某种基础类型(通常会有不明确的值)也会初始化为0

int i;//i的值未定义
int j{};//j被初始化为0
int *p;//值未定义
int *P{};//p被初始化为nullptr

(4)窄化:精度降低或造成数值变动。对大括号是不成立的

int x1(5.3);//ok,x1 = 5
int x2 = 5.3;//ok,x2 = 5;
int x3{5.0};//错误,窄化
int x4 = {5.3};//错误,窄化
char c1{7};//ok
char c2{99999};//error:窄化:99999不是一个char型
std::vector<int>v1{1,2,4,5};//ok
std::vector<int>v2{12.345.6}//error:窄化

1)判定是否窄化转换是,依赖初值设定的实际值而非只是依赖类型
2)浮点数转化至整数永远是一种窄化
4.Rang-Based for
(1)为了避免调用每个元素的copy和析构函数,通常应该声明当前元素为一个从const reference。
(2)基本语法

for(decl:coll)
{
	statement
}

当元素在for循环中被初始化为decl,不得有任何显示类型转换

class C
{
public:
	explicit C(const std::string& s);
};
std::vector<std::string>vs;
for(const C &elem:vs)//ERROR
{
	std::cout<<elem<<std::endl;
}

5.Move语义和Rvalue Reference
(1)c++11的一个最重要的的特性就是,支持搬迁语句。用以避免非必要拷贝和临时对象
6.关键字noexceptiom
用来指明某个函数无法或者不打算 抛出异常
(1)运行期检验:C++异常明细乃是被检验于运行期而非编译器,所以它无法对程序员保证每个异常都被处理。
(2)运行期开销:运行期检验会令编译器产出额外代码且妨碍优化。
(3)无法用于泛型码中:
7.关键字constexpr
用于让表达式核定于编译器

constexpr int square(int x)
{
	return x*x;
}

8.带别名的模板

template<typename T>
using Vec = std::vector<T,MyAlloc<T>>;

Vec coll;
等价于std::vector<int,MyAlloc>coll;
10.Lambda
(1)lambda不可以是template,必须知名所有类型
(2)用于访问外部作用域的方法
1)[=]外部作用域以值传递方式传递给Lambda
可以读取所有可以读取的数据但不能改动他们
2)[&]以引用方式传递给Lambda
对所有可以涂改进行涂写动作都合法。
(3)为了获得passing by value和passing by reference 混合体,可以声明Lambda为mutable

auto f = [id]()mutable{
	std::cout<<"id: "<<std::endl;
	++id;
}

二、虽旧犹新的语言特性
(1)Member template 的一个特殊形式是template构造函数。这种东西通常被提供用于“对象被复制时给予隐式类型转换”的能力。
注意:template构造函数并不压制copy构造函数的隐式声明。如果完全吻合,隐式的copy构造函数会被生成出来,并被调用。

template<typename T>
class Myclass{

public:
	template<typename U>
	MyClass(const MyClass<U>& );
};

void f()
{
	MyClass<double>xd;
	MyClass<double>xd2(xd);
	MyClass<int>xi(xd);
}

1.基础类型的明确初始化
(1)如果使用“一个明确的构造函数调用,但不给实参”,这样的语法,基础类型会被设定初始值为0

int i1;//未定义的值
int i2 = int();//被初始化为0
int i3{}//被初始化为0

2.main()定义式
(1)唯一“正确且具有移植性”的main()。
根据c++标准,main()只有两种定义式具备可移植性

int main()
{
	...
}

int main(int argc,char * argv[])
{
	...//argv,命令行实参形成的array
}

(2)可以(但非必要)以一个return语句终结main()
这意味着,任何程序离开main()时可以不写return语句。0以外的任何值都代表某种失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值