C98和C03对在构建复杂系统时已经可以胜任,并且在作用域、安全等方面已经可以满足现有的需求。C11增加的部分主要针对于程序员容易犯错误的部分进行优化,使其专心于C++项目本身而不是Cplusplus本身,C11主要在枚举和指针方面做出改进,使其天然的“安全”。
强类型枚举类
C++目前较长使用的分门别类的方法主要有三种:命名枚举:enum Gender { Male, Female}+匿名枚举:enum { Male, Female};宏定义:#define Male 0; 静态常量:const static int Male = 0。
枚举在有namespace的命名空间内使用稍显麻烦,一般编译器不会报错,且不同枚举内名称不能相同,一般在比较时转换为int类型,没有类型的属性(枚举可以直接和int比较和转换);宏定义简单替换,只在预处理有意义;静态常量:const static占用储存空间(详见:《深入理解C++11新特性解析与应用》第5.1节)。
C11引进一种新的枚举类型,即枚举类/强类型枚举,在enum后加关键字class即可。
如:enum class Type { General,Light,Medium,Heavy);
优点如下:
◆強作用域,强类型枚举成员不会输出到其父类作用空间;
◆强制转换限制,无法隐式的转换类型,但可以(int)X的形式转换;
◆枚举类可以指定底层数据类型:enum clsaa Type:char{General, Light, Medium, Heavy};
C11之前内存和指针可以改进的地方
C98/03指针(显示管理)从编码角度说,容易出现以下状况:
1 . 内存泄露:不需要使用的内存未释放,导致程序内存集聚增加。
2 . 野指针:已经释放内存的指针为设为NULL,依然使用,指向为知区域,1导致无法预料的错误;
3 . 重复释放:程序试图释放已经释放的内存单元或者已经重新分配的内存单元,造成重复释放,导致无法预计错误,Linux系统中这种情况打印出大量的错误;
让程序员摆脱内存管理的细节,专注于业务和逻辑,是智能指针的设计初衷,但是auto_ptr指针在使用时不太符合C11的左值等原则,不能调用delete等,所以在C++11中auto_ptr被废弃,引入:unique_ptr、share_ptr和weak_ptr等职能指针来自动回收堆分配的对象。
智能指针总结概论
在现代 C++ 编程中,标准库包含智能指针,该指针用于确保程序不存在内存和资源泄漏且是异常安全的。
unique_ptr
只允许基础指针的一个所有者。 除非你确信需要 shared_ptr,否则请将该指针用作 POCO 的默认选项。 可以移到新所有者,但不会复制或共享。 替换已弃用的auto_ptr。 与 boost::scoped_ptr 比较。 unique_ptr 小巧高效;大小等同于一个指针且支持 rvalue 引用,从而可实现快速插入和对 STL 集合的检索。 头文件:。
shared_ptr
采用引用计数的智能指针。 如果你想要将一个原始指针分配给多个所有者(例如,从容器返回了指针副本又想保留原始指针时),请使用该指针。 直至所有shared_ptr 所有者超出了范围或放弃所有权,才会删除原始指针。 大小为两个指针;一个用于对象,另一个用于包含引用计数的共享控制块。 头文件:。
weak_ptr
结合 shared_ptr 使用的特例智能指针。 weak_ptr 提供对一个或多个 shared_ptr 实例拥有的对象的访问,但不参与引用计数。 如果你想要观察某个对象但不需要其保持活动状态,请使用该实例。 在某些情况下,需要断开 shared_ptr 实例间的循环引用。 头文件:
#include <memory>
#include <iostream
using namespace std;
void Check(weal_ptr<int> &wp);
int main(){
//unique_ptr
unique_ptr<int> up1(new int(11));
// unique_ptr<int> up2 = up1; //不能编译通过
unique_ptr<int> up3 = move(up1);
cout << *up3 < <endl; //11
cout<< *up3 << endl; //运行错误
up3.reset(); //显示释放内存
up1.reset(); //不会导致运行错误
// shared_ptr
shared_ptr<int> sp1(new int(22));
shared_ptr<int> sp2 = sp1;
cout<< *sp1 << endl; //22
cout<< *sp2 << endl; //22
sp1.reset();
cout<< *sp2 << endl; //22
// weal_ptr
shared_ptr<int> sp3(new int(33));
shared_ptr<int> sp4 = sp3;
weak_ptr<int> wp = sp3; // 指向 shared_ptr<int>对象;
cout<< *sp3 << endl; //33
cout<< *sp4 << endl; //33
check(wp); //still 33
sp3.reset();
cout<< *sp3 << endl; //33
check(wp); //still 33
sp4.reset();
check(wp); //pointer is invalid
}
void Check(weak_ptr<int> &wp) {
shared_ptr<int> sp = wp.lock(); //转换为share_ptr<int>
if (sp != nullptr)
cout << "stil" << *sp << endl;
else
cout << "pointer is invalid"<<endl;
}
程序解析:
uique_ptr和shared_ptr均来自自动释放对象的内存。指针重载了*符号,可以直接饮用该内存,当该对象析构或者调用reset成员函数时,指针都可能释放其拥有的堆内存。
uique_ptr与所指对象/内存空间绑定紧密,不能与其他uique_ptr共享所指向对象的内存。其“所有权”仅能通过标准库函数move来转移。一旦被转移,该指针失去所有权,再次引用其所有权会导致运行错误。
shared_ptr允许多个智能指针共享的“拥有”同一堆分配对象的内存。与uique_ptr不同,由于在实现上采用了引用计数,所以一旦一个shared_ptr放弃了对对象内存的“所有权”,其他shared_ptr对内存对象的引用并不会受到引线。只有在引用计数为零时,shared_ptr才会释放其堆内存的空间。
weak_ptr可以指向shared_ptr指向的对象内存,却并不拥有该内存。而使用weak_ptr成员lock(),则可返回其指向内存的一个shared_ptr:对象,且在所指对象内存已经无效时,返间指针空值nullptr。