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. 解决clion2016.3不能支持搜狗输入法的问题

    参考链接http://www.cnblogs.com/chentq/p/4975794.html 打开clion.sh在文件头部添加 export GTK_IM_MODULE=fcitx export ...

  2. Entity Framework 6.0 对枚举的支持/实体添加后会有主键反回

    实验 直接上代码,看结果 实体类 [Flags] public enum FlagsEnum { Day = , Night = } public class EntityWithEnum { pub ...

  3. 简单拼接图像的tile_images和tile_images_offset算子

    有时候通常需要简单的拼图,不涉及图像融合之类的,仅仅是简单的平移将多张图拼接成一张图.tile_images和tile_images_offset就是用于简单拼图的2个算子. 谈到拼图,肯定有以下问题 ...

  4. Greeplum 系列(七) 权限管理

    Greeplum 系列(七) 权限管理 一.角色管理 Role 分为用户(User)和组(Group),用户有 login 权限,组用来管理用户,一般不会有 login 权限.初始化 gp 时创建了一 ...

  5. Chrome Console API 参考

    https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference

  6. 安装Oracle数据库时出现网络配置需求检查失败

    提示方法:将 Microsoft LoopBack Adapter 配置为系统的主网络适配器.  解决方法:  控制面板->添加硬件->是,(win7及之后没有添加硬件这个选项了,可以在c ...

  7. redis 设置认证

    server 使用帮助 [root@VM_7_88_centos src]# ./redis-server -h Usage: ./redis-server [/path/to/redis.conf] ...

  8. ADO接口之_RecordsetPtr

    转自:http://hi.baidu.com/%CE%D2%B6%CF%C1%CB%CB%BC%C4%EE/blog/item/e057c526c6af6c29c995596e.html _Recor ...

  9. 团体程序设计天梯赛L2-021 点赞狂魔 2017-04-18 11:39 154人阅读 评论(0) 收藏

    L2-021. 点赞狂魔 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 微博上有个"点赞"功能,你可以为你 ...

  10. 企业搜索引擎开发之连接器connector(十八)

    创建并启动连接器实例之后,连接器就会基于Http协议向指定的数据接收服务器发送xmlfeed格式数据,我们可以通过配置http代理服务器抓取当前基于http协议格式的数据(或者也可以通过其他网络抓包工 ...