C++11新特性大全+实例
C++ 这门编程语言的历史可以追溯至 1979 年,当时的 Bjarne Stroustrup(C++ 之父,后续简称 Stroustrup)还在使用 Simula 语言进行开发工作。
1998 年,C++ 标准委员会发布了第一版 C++ 标准,并将其命名为 C++ 98 标准。据不知名人士透露,《带注释的C++参考手册》这本书对 C++ 98 标准的制定产生了很大的影响。
经过作者的不断迭代,一本书往往会先后发布很多个版本,其中每个新版本都是对前一个版本的修正和更新。C++ 编程语言的发展也是如此。截止到目前(2020 年),C++ 的发展历经了以下 3 个个标准:
2011 年,新的 C++ 11 标准诞生,用于取代 C++ 98 标准。
2014 年,C++ 14 标准发布,该标准库对 C++ 11 标准库做了更优的修改和更新;
2017 年底,C++ 17 标准正式颁布;
虽然学习 C++11 需要花些时间,但这是非常值得的;C++11 非常实用,它不但提高了开发效率,还让程序更加健壮和优雅。程序员应该乐于升级换代已有的知识,而学习和使用 C++11 早就是大势所趋。
|版本声明:山河君,未经博主允许,禁止转载
百度词条:智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象。
从使用上简单来说:智能指针就是包含重载运算符的类,它能够将将普通的指针封装为一个栈对象并进行追踪。
程序猿在申请内存时基本都是 new/delete,进行一一对应,手动申请后要进行手动释放。如果忘记释放就会造成内存泄漏。
使用智能指针就是为了避免此类问题的发生,因为智能指针是一个类,在使用时就可以不用关心有没有释放智能指针所指向的内存,因为类对象超出作用域的时候,会自动调用析构函数释放资源。
4种智能指针:auto_ptr, unique_ptr,shared_ptr, weak_ptr 。其中auto_ptr因为在使用场合中会出现一些我们不希望的场景,它存在潜在的内存崩溃问题!目前已弃用,被unique_ptr所替代。
这篇记录是专门讲解unique_ptr智能指针,并会简单和auto_ptr进行对比。
智能指针类重载了解除引用运算符(*)和成员选择运算符(->)。
几乎所有的智能指针都是模板类,包含其功能的泛型实现。
#include
using namespace std;
class Test {
public:
Test()
{
strTest = "hello world";
cout << "this is init" << endl;
}
~Test()
{
cout << "this is release" << endl;
}
void print()
{
cout << strTest << endl;
}
private:
string strTest;
};
int main()
{
Test* test1 = new Test();
unique_ptr<Test> p(test1);
(*p).print();
}
输出:
这里可以看到,虽然我们没有手动释放类对象,但是依旧调用了类对象的析构函数。
unique_ptr持有对象独有权,即保证保证同一时间内只有一个智能指针可以指向该对象。这一点与auto_ptr一样。
(1)例一
首先看一下auto_ptr
#include
using namespace std;
int main()
{
auto_ptr<string> q1(new string("123"));
auto_ptr<string> q2;
q2 = q1;
cout << *q2 << endl;
cout << *q1 << endl;
}
结果:
直接出现段错误,这是因为同一时间内只有一个智能指针可以指向该对象。但是auto_ptr可以进行重载“=”进行赋值,这样使用就会导致内存崩溃,也是弃用auto_ptr的原因。
使用unique_ptr则不能进行“=”赋值
(2)例二
如果想要进行赋值那应该怎么写呢?
unique_ptr<string> q1(new string("123"));
unique_ptr<string> q2;
q2 = move(q1);
(3)例三
还是Test那个例子
int main()
{
Test* test1 = new Test;
unique_ptr<Test> p1(test1);
unique_ptr<Test> p2(test1);
(*p1).print();
(*p2).print();
}
结果:可以进行同时访问,但是同一块内存释放了两次,所以尽量不要让unique_ptr指针去维护已经使用new返回值初始化的指针,尽量写成这样unique_ptr
(1)例一
这种传参不成功跟上文一样,所以如果使用智能指针进行传参,需要使用引用方式,或是使用std::move的方式。
(2)例二
返回值为智能指针是可以的
unique_ptr<Test> fun2()
{
Test* test1 = new Test;
unique_ptr<Test> p1(test1);
return p1;
}
int main()
{
unique_ptr<Test> p2 = fun2();
(*p2).print();
}
结果:为什么这里可以p2 = p1,这里实际上优先move constructor;可以理解为自动调用了move方法。
(1)release
释放其关联的原始指针的所有权,并返回原始指针。
这里的释放并不会摧毁其指向的对象,而是将其指向的对象释放出去。
int main()
{
Test* test1 = new Test;
unique_ptr<Test> p1(test1);
unique_ptr<Test> p2(test1);
p1.release();
(*p2).print();
}
结果:此时并没有造成同一块内存释放两次,且没有在release时进行析构
(2)reset
释放指向的内存,并且释放了对这块内存的所有权
int main()
{
string* str1 = new string("123");
string* str2 = new string("456");
unique_ptr<string> p1(str1);
p1.reset(str2);
cout << *p1 << endl;
}
结果:
(3)swap
交换两个unique_ptr指针指向区域(交换地址)
int main()
{
string* str1 = new string("123");
string* str2 = new string("456");
unique_ptr<string> p1(str1);
unique_ptr<string> p2(str2);
cout << *p1 << endl;
cout << *p2 << endl;
p1.swap(p2);
cout << *p1 << endl;
cout << *p2 << endl;
}
(4)get
返回unique_ptr维护的指针地址
int main()
{
unique_ptr<int> ptr(nullptr);
ptr = make_unique<int>(10);
cout << *ptr.get() << endl; // 返回10
}
当对象中又包含到多层申请的内容,不能完全依靠智能指针删除时,例如对象中还包含指针指向一块内存的时候。就需要自定义删除方法了。
主要就是自己编写一个删除器,指定输入的参数,然后实现相应的释放操作,并将这个删除器传入 unique_ptr 中。
(1)步骤1
假设有这么一个的结构体定义如下
// 图像格式定义
typedef struct cv_image_t {
unsigned char *data; ///< 指向申请内存
int width; ///< 宽度(以像素为单位)
int height; ///< 高度(以像素为单位)
} cv_image_t;
(2)步骤2
再写一个释放方法
void cv_image_release(cv_image_t* image) {
if(!image) {
return;
}
delete[] image->data;
delete image;
return;
}
(3)步骤3
使用智能指针进行释放
cv_image_t image_input = {
(unsigned char*) image,
image_width,
image_height,
};
//传入对象,和释放方法
std::unique_ptr<cv_image_t, decltype(cv_image_release)*> image_guard (image_input , cv_image_release);
如果对您有用,不妨点个赞涨涨积分!