1. C++11保证稳定性与兼容性
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保证稳定性与兼容性的更多相关文章
- C++11新标准学习
<深入理解C++11:C++11新特性解析与应用> <华章科技:深入理解C++11:C++11新特性解析与应用>一共8章:第1章从设计思维和应用范畴两个维度对C++11新标准中 ...
- c++学习书籍推荐《深入理解C++11 C++11新特性解析与应用》下载
百度云及其他网盘下载地址:点我 编辑推荐 <深入理解C++11:C++11新特性解析与应用>编辑推荐:C++标准委员会成员和IBM XL编译器中国开发团队共同撰写,权威性毋庸置疑.系统.深 ...
- 深入理解C++11 阅读笔记
二 保证稳定性和兼容性保持与C99兼容 预定义宏 C99语言标准增加的一些预定义宏,C++11同样增加了对这些宏的支持 __func__预定义标识符 功能是返回所在函数的名字,在C++11中,标准甚至 ...
- iOS App稳定性指标及监测
一个App的稳定性,主要决定于整体的系统架构设计,同时也不可忽略编程的细节,正所谓"千里之堤,溃于蚁穴",一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系统的崩溃.尤其因为 ...
- 问题11:web前端开发规范手册(转)
一.规范目的 1.1 概述 ..................................................................................... ...
- 2013 duilib入门简明教程 -- 部分bug (11)
一.WindowImplBase的bug 在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题, 1.最大化按钮的样式 ...
- c++11中的static
超赞的线程安全的初始化 static plsa::PLSAModel& model() { static plsa::PLSAModel _model = ([&]() { plsa: ...
- 安卓CTS官方文档之兼容性方案概览
兼容性方案概览 安卓的兼容性方案让安卓手机生产商能够很容易就开发中可兼容的安卓设备(天地会珠海分舵注:可兼容什么呢?就是可以兼容标准google提供的安卓系统可以支持的功能,以防手机生产商把开源的安卓 ...
- html-关于IE浏览器兼容性的问题,还有浏览器一直加载的问题。
今天9月11日,所谓兼容性问题就是,标签 写的不规范导致的,因为高版本的IE会自动补上没写的标签 document.write('<object classid="clsid:d27c ...
随机推荐
- Linux CentOS6 mysql rpm安装
mysql rpm文件下载地址:https://dev.mysql.com/downloads/mysql/ 选择操作系统及版本: 点击5.6版本链接 将下载好的文件上传至服务器 下面开始安装: 检查 ...
- [Tools]SurveyMonkey
做问卷调查,推荐一个好工具,免费的 SurveyMonkey : it's free, quick & easy! https://www.surveymonkey.com/
- oracle 分页其实一个子查询就好了,没理解的自然只能见样学样
.首先rownum是一个查询缓存级别的东西,所以以下写法是错误的 ; 因为rn其实不是student表的内容,看做一个缓存编号就好 但是有些人不服了,加个a.rn<= ;结果还是不行,这下相信了 ...
- Andriod 之数据获取
服务端Model using System; using System.Collections.Generic; using System.Linq; using System.Web; namesp ...
- Oracle学习笔记(四)
六.约束 1.约束的作用 定义规则:什么数据可以输入,什么不可以 确保完整性:数据的精确性和可靠性 2.Oracle五个重要的约束: 非空约束.主键约束.外键约束.检查约束.唯一约束. (1)非空约束 ...
- Centos环境下手动设置-网络参数配置-网络挨排错顺序-设置网卡为上网模式的设定
Linux中网络参数大致包含以下内容: IP地址 子网掩码 网关 DNS服务器 主机名(默认 localhost) 历来Linux系统中修改这些参数的方式通常有:命令.文件两种.其中通过命令设置可以立 ...
- 企业搜索引擎开发之连接器connector(二十)
连接器里面衔接数据源与数据推送对象的是QueryTraverser类对象,该类实现了Traverser接口 /** * Interface presented by a Traverser. Used ...
- [转载]关于JAVA中子类和父类的构造方法
原文链接:https://www.cnblogs.com/chenpi/p/5486096.html#_label0
- ubuntu 安装 zend studio
hi,everyone!2014 年到了,是20你死还是爱你一世,世人不得而知.夜观天象,道德依旧在沦丧,经济依然在滑坡.行了,就整这几句.最近在折腾linux,这篇文章,没有什么意义.只是找找写bl ...
- Android-封装JSON数据(JSON对象/JSON数组)
Android-封装JSON数据(JSON对象/JSON数组),一般情况下不会在Android端封装JSON的数据,因为封装JSON的数据是在服务器端进行封装了,Android更多的工作是解析(JSO ...