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 ...
随机推荐
- nginx 负载均衡 使用ip_hash方式解决session问题 测试
ip_hash的方式比较弱智,但是在一般情况下是挺有效的~~,如果能保证nginx是最上一层的代理,那么能够得到用户的ip是真实位置,就能做到负载,但是一家公司的所有员工其实走的是同一个ip,那么在这 ...
- o7 文件和函数
一:文件 1 控制文件内指针的移动 文件内指针移动,只有在t模式下的read(n),n代表的字符的个数 除此之外文件内指针的移动都是以字节为单位的 with open('a.txt',mode ='r ...
- mvc数组绑定-jquery ajax
var list=[];//数组 list[0]=1001; list[1]=1002; list[1]=1003; var json_data = { selected: list}; $.ajax ...
- swift pop实现动感按钮动画
// // MyButton.swift // PopInstall // // Created by su on 15/12/11. // Copyright © 2015年 tian. A ...
- Android UI 之 ListView
一.在代码中创建(不适用XML布局文件) 1.创建一个项目:ListViewLearn 2.修改MainActivity,继承于ListActivity 3.创建一个String数组,用来保存List ...
- Low-level Thinking in High-level Shading Languages
因为要反汇编shader代码,所以google了数学函数_sat的知识,发现了一些高级着色语言的优化相关的问题.Low-level Thinking in High-level Shading Lan ...
- Angularjs 实现页面遮罩层功能
实现效果: 1.loading指令: "use strict" /** * Created by yw on 2015/9/27. * user defined loading d ...
- Python笔记之format()格式输出全解
格式化输出:format() format():把传统的%替换为{}来实现格式化输出 使用位置参数:就是在字符串中把需要输出的变量值用{}来代替,然后用format()来修改使之成为想要的字符串,位置 ...
- 数据与任务的并行---Parallel类
Parallel类是对线程的抽象,提供数据与任务的并行性.类定义了静态方法For和ForEach,使用多个任务来完成多个作业.Parallel.For和Parallel.ForEach方法在每次迭代的 ...
- C# 时间戳与DateTime间的互相转换
//DateTime转换为时间戳public long GetTimeSpan(DateTime time) { DateTime startTime = TimeZone.CurrentTimeZo ...