c++11知识点1_基础

原创 2016年08月29日 14:21:19
1.概述
1.1.背景
C++11(草案原名C++0x)于 2011年9月1日出版发布C++11标准,正式名称为:
ISO/IEC 14882:2011 - Information technology -- Programming languages -- C++
取代1998年发布的C++标准第一版(C++98标准,全称ISO/IEC 14882:1998)和2003年发布的C++标准
第二版(C++03标准,全称ISO/IEC 14882:2003)。


1.2.改进之处
核心语言的领域被大幅改善,包括多线程支持、 泛型编程、统一的初始化,以及表现的加强。


(1)右值引用和转移语义
在旧标准C++语言中,临时量(术语为右值,因其出现在赋值表达式的右边)可以做参数传给函数,但只能被
接受为const &类型。这样函数便无法区分传给const &的是真正的右值还是普通const变量。而且,由于
类型为const &,函数也无法改变所传对象的值。


C++0x将增加一种名为右值引用的新的引用类型,记作typename &&。这种类型可以被接受为非const值,
从而允许改变其值。这种改变将允许某些对象创建转移语义。


比如,一个std::vector,就其内部实现而言,是一个C式数组的封装。如果需要创建vector临时量或者从
函数中返回vector,那就只能通过创建一个新的vector并拷贝所有存于右值中的数据来存储数据。之后这
个临时的vector则会被销毁,同时删除其包含的数据。


有了右值引用,一个参数为指向某个vector的右值引用的std::vector的转移构造器就能够简单地将该右值
中C式数组的指针复制到新的vector,然后将该右值清空。这里没有数组拷贝,并且销毁被清空的右值也不会
销毁保存数据的内存。返回vector的函数现在只需要返回一个std::vector<>&&。如果vector没有转移构
造器,那么结果会像以前一样:用std::vector<> &参数调用它的拷贝构造器。如果vector确实具有转移
构造器,那么转移构造器就会被调用,从而避免大量的内存分配。


考虑到安全因素,具名变量即使被声明为右值类型也不会被当作右值。如需把它当作右值,须使用库函数std::move()。


bool is_r_value(int &&)
{
return true;
}
bool is_r_value(const int &)
{
return false;
}
void test(int &&i)
{
is_r_value(i); // false
is_r_value(std::move(i)); // true
}


(2)泛化的常数表示式
C++语言一直具有常量表达式的概念。这些诸如3+4之类的表达式总是产生相同的结果且不具备副作用。
常量表达式给编译器带来了优化的可能,而编译器也经常在编译期执行此类表达式并将结果存放在程序中。
此外,C++语言规范中有一些地方需要使用常量表达式。定义数组需要常量表达式,而枚举值也必须是常量表达式。
然而,每当碰到函数调用或对象构造,常量表达式便不再有效。所以简单如下例便不合法:
int GetFive()
{
return 5;
}
int some_value[GetFive() + 5]; //创建一个包含10个整型变量的数组,在标准C++中不合法


这段代码在C++中不合法,因为GetFive() + 5不是一个常量表达式。
编译器无从知晓GetFive在运行期是否产生常量。
理论上,这个函数可能会影响某个全局变量,或者调用其他运行期产生非常量的函数。
C++0x将引入constexpr关键字,此关键字将使用户能保证某个函数或构造器在编译期产生常量。
上例可被改写如下:
constexpr int GetFive()
{
return 5;
}
int some_value[GetFive() + 5]; //在标准C++0x中合法
这段代码将使编译器理解并确认GetFive是个编译期常量。


在函数上使用constexpr将对函数功能施加严格的限制。
首先,函数必须返回非void类型。
其次,函数体必须具有"return /expr/"的形式。
第三,expr在参数替换后必须是常量表达式。该常量表达式只能调用其他定义为constexpr的函数,只能
使用其他常量表达式数据变量。
第四,常量表达式中一切形式的递归均被禁止。最后,这种带constexpr的函数在编译单元中必须先定义后调用。


变量也可被定义为常量表达式值。
constexpr double forceOfGravity = 9.8;
constexpr double moonGravity = forceOfGravity / 6;
常量表达式数据变量隐含为常量。它们只能存放常量表达式或常量表达式构造器的结果。


为了从用户自定义类型中构建常量表达式数据值,构造器在声明时可带constexpr。
同常量表达式函数一样,在编译单元中常量表达式构造器也必须先定义后使用。
常量表达式构造器函数体必须为空,而且它必须用常量表达式构造其成员。这种类型的析构器必须是平凡的。


由常量表达式拷贝构造的类型也必须被定义为constexpr,以使它们能从常量表达式函数中作为值被返回。
类的任何成员函数,包括拷贝构造器和操作符重载,都能被声明为constexpr,只要它们符合常量表达式函数的定义。
这就允许编译器在编译期不仅能拷贝类对象,也能对其实施其他操作。


常量表达式函数或构造器可以用非constexpr参数来调用。就如同一个constexpr整数常量可以被赋给一个
非constexpr变量一样,constexpr函数也可用非constexpr参数来调用,并且其结果也可存放在非constexpr
变量中。此关键字只是提供了在一个表达式的全部成员均为constexpr时其结果为编译期常量的可能性。


(3)对POD定义的修正
POD,Plain Old Data,指POD用来表明C++中与C相兼容的数据类型,可以按照C的方式来处理(运算、拷贝等)。


C++0x将放松某些关于POD的限制规则。
如果一个类或结构是平凡的,具有标准布局的,且不包含任何非POD的非静态成员,那么它就被认定是POD。
平凡的类或结构定义如下:
<1>.具有一个平凡的缺省构造器。(可以使用缺省构造器语法,如 SomeConstructor() = default;)
<2>.具有一个平凡的拷贝构造器。(可以使用缺省构造器语法)
<3>.具有一个平凡的拷贝赋值运算符。(可以使用缺省语法)
<4>.具有一个非虚且平凡的析构器。


一个具有标准布局的类或结构被定义如下:
<1>.所有非静态数据成员均为标准布局类型。
<2>.所有非静态成员的访问权限(public, private, protected) 均相同。
<3>.没有虚函数。
<4>.没有虚基类。
<5>.所有基类均为标准布局类型。
<6>.没有任何基类的类型与类中第一个非静态成员相同。
<7>.要么全部基类都没有非静态数据成员,要么最下层的子类没有非静态数据成员且最多只有一个基类有非静态数据成员。
总之继承树中最多只能有一个类有非静态数据成员。所有非静态数据成员必须都是标准布局类型。


(4)外部模板
在标准C++语言中,如果在某一个编译单元中编译器碰到一个参数完全指定的模板,它就必须实例化该模板。
这种做法可能大大延长编译时间,尤其在许多编译单元使用同样的参数实例化该模板时。
为了解决此问题,C++0x引入外部模板的概念。


C++已经拥有了迫使编译器在某一地点实例化模板的语法:
template class std::vector<MyClass>;
C++所缺乏的是防止编译器具现化某个模板的能力。
C++0x只是简单地将语法扩展为:
extern template class std::vector<MyClass>;
这段代码将告诉编译器不要在这个编译单元实例化此模板。

相关文章推荐

c++11知识点3_chrono时间模板库

1.概述 chrono是一个time library, 源于boost,现在已经是C++11标准。 要使用chrono库,需要#include,其所有实现均在std::chrono namespa...

C++11并发相关知识点

并发的途径: 1.    多进程并发 将应用程序分为多个、独立的、单线程的进程。 它的特点: (1)这种进程之间的通信通常设置复杂,或是速度较慢,或两者兼备,因为操作系统通常在进程间提供了大量的保护。...

C++11 知识点

l  利用{}进行所有容器和数据结构的就地初始化,还可以直接用于返回值,对自定义类型进行就地初始化使用initializer_list l  通过右值引用,函数可以自由的返回大对象,同时带资源赋值更...

牛客网 8-11 网络基础 操作系统 编译与体系结构 30题知识点总结

1、代码编辑功能是编辑器提供的 代码规范检查也是编辑器提供的 分析代码问题是调试器提供的 编译器主要完成源码向目标代码的转化       2、RS-485分为两大类:两制线、四制线。其中...

数据开发基础知识点-1(提交方式)

  • 2014年09月11日 16:55
  • 117KB
  • 下载

1.Java基础知识点整理(基于毕向东老师)

目录 1.Java基础... 1 Java概述SUN.. 1 Java语言三种技术架构J2EE. 1 Java一些简写JVM.. 1 Java环境变量配置JAVA_HOME. 1 Java名词java...
  • seaoson
  • seaoson
  • 2017年02月03日 13:13
  • 180

Java面试笔试知识点之基础部分1

u011915230 这位csdn的朋友总结了他一年Java面试下来总结的知识点,我将尝试对这些问题做出解答。由于问题太多,将分为多个博客来陈述。 一、Java基础部分  1、public、pri...

牛客网 8-1 网络基础 操作系统 编译与体系结构 30题知识点总结

1、  系统内可以有无父进程的进程。  init进程没有父进程     2、死锁 定义 :在一个进程集合中,所有的进程都在等待只能由该进程集合中的其它进程才能引发的事件,这就是死锁 解释 :...

Java知识点复习1基础备忘

1. Java命名习惯 1)包名字母一律小写; 2)类名,接口名应该使用名词,每个单词首字母大写; 3)方法名,第一个单词小写,后面每个单词首字母大写; 4)变量名,第一个单词小写,后面每个单词首...

基础知识点1

1、java是解释型语言,还是编译型语言?说说你知道的其他的编译型语言和解释型语言 java源程序,先有javac(java编译器)编译成与平台无关的字节码,这些字节码不面向任何具体平台,它只面向J...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++11知识点1_基础
举报原因:
原因补充:

(最多只允许输入30个字)