1.1 __func__预定义标识符

  在c99中,__func__基本功能是返回所在函数的名字,c++11中允许使用在类或结构体中。

 #include <iostream>
using namespace std; struct TestStruct {
TestStruct() : name(__func__) {}
const char *name;
};
int main()
{
TestStruct ts;
cout << ts.name << endl;
return ;
}

执行结果为:

1.2 _Pragma操作符

在c/c++标准中,#pragma是一条预处理的指令。如在代码头文件中定义如下语句

#pragma once

该命令会指示编译器,该头文件只被编译一次。等价于

#ifndef THIS_HEADER
#define THIS_HEADER
// ...
#endif

在C++11标准定义了预处理指令#pragma功能相同的操作符_Pragma,格式如下:

_Pragma( 字符串字面量 )

使用方法同sizeof等操作符一样,_Pragma ("once")  等价于 #pragma once

#define CONCAT(x) PRAGMA(concat on #x)
#define PRAGMA(x) _Pragma(#x) int main()
{
CONCAT(../concat.dir); // 最终会产生 _Pragma(concat on "../concat.dir")
return ;
}

#pragma不支持在宏中展开,而_Pragma支持,C++11的_Pragma具有更大的灵活性。

1.3 变量参数的宏定义__VA_ARGS__

在c99标准中,可以使用参数列表的最后一个参数为省略号来表示变长参数的宏定义。c++11中,预定义宏__VA_ARGS_则可以在宏定义的实现部分替换省略号所代表的字

#include <stdio.h>

#define LOG(...) {\
fprintf(stderr, "%s: Line %d:\t", __FILE__, __LINE__);\
fprintf(stderr, __VA_ARGS__);\
fprintf(stderr, "\n");\
} int main()
{
int x = ;
LOG("x = %d", ); //执行结果 D:\clion_local_project\test3\main.cpp: Line 12: x = 3 return ;
}

1.4 __cplusplus

在c和c++混合编程时,经常看到如下声明

 #ifdef __cplusplus
extern "C" {
#endif
//一些代码
#ifdef __cplusplus
};
#endif

这种类型的头文件可以在c程序中进行编译,也可以在c++程序进行编译。在c++03标准中,__cplusplus的值被预定为199711L,而c++11中为201103L,这个变化可以为代码所用,例如想使用C++11进行编译时,可以使用如下方法:

#if __cplusplus < 201103L
#error "should use C++11 implementation"
#endif

这样不支持C++11的代码编译会立即报错,并终止编译。

1.5 static_assert静态断言

断言assert宏只有在程序运行时才起作用(动态断言),而#error只有在编译器预处理时才能起作用。

 #include <cassert>
#include <cstring>
using namespace std; template <typename T, typename U> int bit_copy(T &a, U &b) {
assert(sizeof(a) == sizeof(b));
memcpy(&a, &b, sizeof(b));
}; int main() {
int a = 0x2568;
double b;
bit_copy(a, b);
}

如上,代码编译期间无法触发断言。使用static_assert即可在编译期间触发断言异常。

 template <typename T, typename U> int bit_copy(T &a, U &b) {
static_assert(sizeof(a) == sizeof(b), "the parameters of bit_copy must have same width");
memcpy(&a, &b, sizeof(b));
}; int main() {
int a = 0x2568;
double b;
bit_copy(a, b);
}

编译报错:

1.6 noexcept操作符

在c++11中,如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()函数来终止程序的运行,阻止了异常的传播,这比基于throw()的效率更高。

#include <iostream>
using namespace std; void Throw() {throw ;}
void NoBlockThrow() {Throw();}
void BlockThrow() noexcept {Throw();} int main() {
try {
Throw();
}
catch (...) {
cout << "Found throw." << endl;
} try {
NoBlockThrow();
}
catch (...) {
cout << "Throw is not blocked." << endl;
} try {
BlockThrow();
}
catch (...) {
cout << "Found throw 1." << endl;
}
}

noexcept更大的作用是保证程序的安全,C++11让类中的析构函数默认也是noexcept(true)的,如果显示地为析构函数指定了noexcept,或者类的基类或成员有noexcept(false)的析构函数,析构函数就不会保持默认值。

#include <iostream>
using namespace std; struct A {
~A() {throw ;}
}; struct B {
~B() noexcept(false) {throw ;}
}; struct C {
B b;
}; int funA() { A a; }
int funB() { B b; }
int funC() { C c; } int main()
{
try {
funB();
}
catch (...) {
cout << "caught funB." << endl;
} try {
funC();
}
catch (...) {
cout << "caught funC." << endl;
} try {
funA();
}
catch (...) {
cout << "caught funA." << endl;
}
}

1.7 非静态成员的sizeof

#include <iostream>
using namespace std; struct People{
public:
int hand;
static People *all;
}; int main()
{
People p;
cout << sizeof(p.hand) << endl; //C++98中通过, C++11中通过
cout << sizeof(People::all) << endl; //C++98中通过, C++11中通过
cout << sizeof(People::hand) << endl; //C++98中错误, C++11中通过
}

注意最后一个sizeof操作,在C++11中,对非静态成员变量使用sizeof操作是合法的。而在C++98中,只有静态成员,或者对象的实例才能对其成员进行sizeof操作。在C++98中,可以强制转换0为1个People类的指针,继而通过指针的解引用获取其成员变量,再通过sizeof获取大小

sizeof(((People*))->hand);

1.8 friend的扩展

在C++11中,声明一个类为另外一个类的友元时,不再需要关键字class。这个特性可以为类的模板声明友友元了。

class P;
template <typename T> class People {
friend T;
}; People<P> PP; //类P在这里是PP的友元
People<int> Pi; //对于int类型的模板参数,友元声明被忽略,这样我们可以在模板实例化时才确定一个模板类是否有友元。
#include <iostream>
using namespace std; template <typename T> class DefenderT {
public:
friend T;
void Defence(int x, int y) {}
void Tackle(int x, int y) {} private:
int pos_x = ;
int pos_y = ;
int speed = ;
int stamina = ;
}; template <typename T> class AttackerT {
public:
friend T;
void Move(int x, int y) {}
void SpeedUp(float ratio) {} private:
int pos_x = ;
int pos_y = -;
int speed = ;
int stamina = ;
}; using Defender = DefenderT<int>; //普通类定义,使用int做参数
using Attacker = AttackerT<int>; class Validator;
using DefenderTest = DefenderT<Validator>; //测试专用的定义,Validator类成为友元
using AttackerTest = AttackerT<Validator>; class Validator {
public:
void Validate(int x, int y, DefenderTest &d) {d.pos_x = x;} //通过友元来访问
void Validate(int x, int y, AttackerTest &a) {a.speed = y;} //通过友元来访问
}; int main()
{
DefenderTest d;
AttackerTest a;
a.Move(, );
d.Defence(, );
Validator v;
v.Validate(, , d);
v.Validate(, -, a); return ;
}

1.9 final/override控制

final关键字的作用是使派生类不可覆盖它所修饰的虚函数。

如果派生类在虚函数声明时使用了override描述符,那么该函数必须重载其基类中的同名函数。

1.10 模板函数的默认模板参数

C++98模板类声明时允许其有默认的模板参数,却不支持函数模板的默认模板参数,C++11中已经支持。

有多个模板参数时,类模板指定默认值必须“从右往左”的规则进行指定,而函数模板并不是必须的。

1.11 外部模板

使用extern显示的实例化模板。

1.12 局部和匿名类型作为模板参数

C++11 支持局部和匿名类型作为模板的参数。

template <typename T> class X {};
template <typename T> void TempFun(T t) {};
struct A{} a;
struct {int i;} b; // b是匿名类型变量
typedef struct {int i;} B; // B是匿名类型结构体 void Fun()
{
struct C {} c;
X<A> x1; // C++98通过, C++11通过
X<B> x2; // C++98错误, C++11通过
X<C> x3; // C++98错误, C++11通过
TempFun(a); // C++98通过, C++11通过
TempFun(b); // C++98错误, C++11通过
TempFun(c); // C++98错误, C++11通过
}

1. C++11保证稳定性与兼容性的更多相关文章

  1. C++11新标准学习

    <深入理解C++11:C++11新特性解析与应用> <华章科技:深入理解C++11:C++11新特性解析与应用>一共8章:第1章从设计思维和应用范畴两个维度对C++11新标准中 ...

  2. c++学习书籍推荐《深入理解C++11 C++11新特性解析与应用》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <深入理解C++11:C++11新特性解析与应用>编辑推荐:C++标准委员会成员和IBM XL编译器中国开发团队共同撰写,权威性毋庸置疑.系统.深 ...

  3. 深入理解C++11 阅读笔记

    二 保证稳定性和兼容性保持与C99兼容 预定义宏 C99语言标准增加的一些预定义宏,C++11同样增加了对这些宏的支持 __func__预定义标识符 功能是返回所在函数的名字,在C++11中,标准甚至 ...

  4. iOS App稳定性指标及监测

    一个App的稳定性,主要决定于整体的系统架构设计,同时也不可忽略编程的细节,正所谓"千里之堤,溃于蚁穴",一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系统的崩溃.尤其因为 ...

  5. 问题11:web前端开发规范手册(转)

    一.规范目的 1.1  概述 ..................................................................................... ...

  6. 2013 duilib入门简明教程 -- 部分bug (11)

     一.WindowImplBase的bug     在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题,     1.最大化按钮的样式 ...

  7. c++11中的static

    超赞的线程安全的初始化 static plsa::PLSAModel& model() { static plsa::PLSAModel _model = ([&]() { plsa: ...

  8. 安卓CTS官方文档之兼容性方案概览

    兼容性方案概览 安卓的兼容性方案让安卓手机生产商能够很容易就开发中可兼容的安卓设备(天地会珠海分舵注:可兼容什么呢?就是可以兼容标准google提供的安卓系统可以支持的功能,以防手机生产商把开源的安卓 ...

  9. html-关于IE浏览器兼容性的问题,还有浏览器一直加载的问题。

    今天9月11日,所谓兼容性问题就是,标签 写的不规范导致的,因为高版本的IE会自动补上没写的标签 document.write('<object classid="clsid:d27c ...

随机推荐

  1. 使用C#进行基于PI的开发

    首先欲基于PI-SDK开发PI数据库,必须先安装PI-SDK,然后再VS中新建了一个aspnet网站,添加引用:PI-SDK 1.2 Type Library 和 PISDKCommon 1.2 Ty ...

  2. 使用mybatis提供的各种标签方法实现动态拼接Sql。使用foreach标签实现遍历查询。比如实现select * from user where id in(1,10,24)这条sql查询语句。

    向sql传递数组或List,mybatis使用foreach解析,如下: 需求: 传入多个id查询用户信息,用下边的sql实现: select * from user where id in(1,10 ...

  3. CentOS7防火墙firewall相关操作

    1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld 停止: systemctl disabl ...

  4. 一些使用的linux库

    1.curl网络库 apt-get install libcurl4-openssl-dev sudo apt-get install curl 2.jsoncpp库 sudo apt-get ins ...

  5. qt学习(二) buttong layout spinbox slider 示例

    开启qt5 creator 新建项目 qt widgets 改写main.cpp #include "mainwindow.h" #include <QApplication ...

  6. meterpreter命令

    meterpreter详解与渗透实战 基本命令: background quit shell irb client.sys.config.sysinfo() 调用windows API:client. ...

  7. 课堂限时训练-简易计算器·mini dc

    课堂限时训练-简易计算器·mini dc 实验题目 采用后缀表达式法,设计一个建议计算器,实现+.-.*./四种运算. 代码实现 码云链接 关键代码部分及结果如下: 实验分析 首先,分析一下后缀表达式 ...

  8. android分屏

    上手了Android N Preview,第一个不能错过的新特性就是App分屏的支持.Android7.0原生系统就可以支持两个App横屏并排或者竖屏上下摆放了.第二个新特性就是在Android TV ...

  9. Vivado 2017封装自定义IP Core

    使用Vivado2017.3自定义IP Core.通常情况下,我们做设计采用模块化设计,对于已经设计好的一部分模块功能,就可以直接拿来调用,IP Core就是这样来的,一般来说我们看不到IP Core ...

  10. 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)

    题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...