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 ...
随机推荐
- Laravel中Trait的用法实例详解
本文实例讲述了Laravel中Trait的用法.分享给大家供大家参考,具体如下: 看看PHP官方手册对Trait的定义: 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 trait ...
- centos7 dubbokeeper安装
下载dubbokeeper源码 git clone https://github.com/dubboclub/dubbokeeper mysql 先执行install-mysql.sh 编译好 ...
- 信息增益(Information Gain)(转)
当我们需要对一个随机事件的概率分布进行预测时,我们的预测应当满足全部已知的条件,而对未知的情况不要做任何主观假设.在这种情况下,概率分布最均匀,预测的风险最小.因为这时概率分布的信息熵最大,所以称之为 ...
- Centos 7 手把手教你使用YUM方式安装并配置Nginx+php7-fpm+MySQL
需要准备的内容 一台纯净系统的服务器 远程连接服务器的工具 (我这里使用Xshell) 安装nginx 链接上服务器后执行 yum install nginx 这里需要输入y 后回车,开始安装ngi ...
- (匹配 Hopcroft-Karp算法)Rain on your Parade -- Hdu --2389
链接: http://acm.hdu.edu.cn/showproblem.php?pid=2389 不能用匈牙利,会TEL的,用Hopcroft-Karp Hopcroft-Karp课件 以前是寻找 ...
- (1)-使用json所要用到的jar包下载
json是个非常重要的数据结构,在web开发中应用十分广泛.我觉得每个人都应该好好的去研究一下json的底层实现,需要准备下面的六个jar包:commons-lang-1.0.4.jar common ...
- Oracle ERP Profile
1.配置系统 . 进入路径:SYSADMIN 登录,系统管理员--Profile--系统: 配置分类 配置文件 文件选项 内容 配置系统 ICX% ICX:日期显示样式 选择修改日期输 入格式(199 ...
- tomcat7-maven-plugin 端口
不知道有没有人像我这样,在pom配置了下面这段之后, <plugins> <plugin> <groupId>org.apache.tomcat.maven< ...
- kubernetes 滚动更新发布及回滚
基本命令 记录历史 --record kubectl apply -f **** --record 查看当前状态 kubectl rollout status deployment/demo -w ...
- oracle 批量删除触发器
--生成删除触发器的语句 select 'drop trigger "'||trigger_name||'";' from all_triggers where TRIGGER_ ...