配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。
C++11中提供了三种智能指针,使用这些智能指针时需要引用头文件<memory>:
std::shared_ptr:共享的智能指针
std::unique_ptr:独占的智能指针
std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视shared_ptr的。
1. shared_ptr的初始化共享智能指针是指多个智能指针可以同时管理同一块有效的内存,共享智能指针shared_ptr 是一个模板类,如果要进行初始化有 ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. move在C++11添加了右值引用,并且不能使用左值初始化右值引用,如果想要使用左值初始化一个右值引用需要借助std::move()函数,使用std::move方法可以将左值转换为右值。使用这个函数并不能移动任何东西,而是和移动构造函数一样都具有移动语义,将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存拷贝。
从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue);,函数原型如下:
12345template<class _Ty>_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) _NOEXCEPT{ // forward _Arg as movable return (static_cast<remove_re ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. 右值引用1.1 右值C++11 增加了一个新的类型,称为右值引用( R-value reference),标记为 &&。在介绍右值引用类型之前先要了解什么是左值和右值:
lvalue 是loactor value的缩写,rvalue 是 read value的缩写
左值是指存储在内存中、有明确存储地址(可取地址)的数据;
右值是指可以提供数据值的数据(不可取地址);
通过描述可以看出,区分左值与右值的便捷方法是:可以对表达式取地址(&)就是左值,否则为右值 。所有有名字的变量或对象都是左值,而右值是匿名的。
123int a = 520;int b = 1314;a = b;
一般情况下,位于=前的表达式为左值,位于=后边的表达式为右值。也就是说例子中的a, b为左值,520,1314为右值。a=b是一种特殊情况,在这个表达式中a, b都是左值,因为变量b是可以被取地址的,不能视为右值。
C++11 中右值可以分为两种 ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在C++中using用于声明命名空间,使用命名空间也可以防止命名冲突。在程序中声明了命名空间之后,就可以直接使用命名空间中的定义的类了。在C++11中赋予了using新的功能,让C++变得更年轻,更灵活。
1. 定义别名在 C++中可以通过 typedef 重定义一个类型,语法格式如下:
123typedef 旧的类型名 新的类型名;// 使用举例typedef unsigned int uint_t;
被重定义的类型并不是一个新的类型,仅仅只是原有的类型取了一个新的名字。和以前的声明语句一样,这里的声明符也可以包含类型修饰,从而也能由基本数据类型构造出复合类型来。C++11中规定了一种新的方法,使用别名声明(alias declaration)来定义类型的别名,即使用using。
在使用的时候,关键字using作为别名声明的开始,其后紧跟别名和等号,其作用是把等号左侧的名字规定成等号右侧类型的别名。类型别名和类型的名字等价,只要是类型的名字能出现的地方,就能使 ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. 基本用法lambda表达式是C++11最重要也是最常用的特性之一,这是现代编程语言的一个特点,lambda表达式有如下的一些优点:
声明式的编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或函数对象。
简洁:避免了代码膨胀和功能分散,让开发更加高效。
在需要的时间和地点实现功能闭包,使程序更加灵活。
lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。lambda表达式的语法形式简单归纳如下:
1[capture](params) opt -> ret {body;};
其中capture是捕获列表,params是参数列表,opt是函数选项,ret是返回值类型,body是函数体。
捕获列表[]: 捕获一定范围内的变量
参数列表(): 和普通函数的参数列表一样,如果没有参数参数列表可以省略不写。
12auto f = [](){return 1;} // 没有参数, ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. 可调用对象在C++中存在“可调用对象”这么一个概念。准确来说,可调用对象有如下几种定义:
是一个函数指针
1234567int print(int a, double b){ cout << a << b << endl; return 0;}// 定义函数指针int (*func)(int, double) = &print;
是一个具有operator()成员函数的类对象(仿函数)
1234567891011121314151617181920#include <iostream>#include <string>#include <vector>using namespace std;struct Test{ // ()操作符重载 void operator()(string msg) { ...
C++
未读
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在C++98/03中,不同的容器和数组遍历的方式不尽相同,写法不统一,也不够简洁,而C++11基于范围的for循环可以以简洁、统一的方式来遍历容器和数组,用起来也更方便了。
1. for循环新语法在介绍新语法之前,先来看一个使用迭代器遍历容器的例子:
123456789101112131415#include <iostream>#include <vector>using namespace std;int main(){ vector<int> t{ 1,2,3,4,5,6 }; for (auto it = t.begin(); it != t.end(); ++it) { cout << *it << " "; } cout << endl; r ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
关于C++中的变量,数组,对象等都有不同的初始化方法,在这些繁琐的初始化方法中没有任何一种方式适用于所有的情况。为了统一初始化方式,并且让初始化行为具有确定的效果,在C++11中提出了列表初始化的概念。
1. 统一的初始化在C++98/03中,对应普通数组和可以直接进行内存拷贝(memcpy())的对象是可以使用列表初始化来初始化数据的
12345678910// 数组的初始化int array[] = { 1,3,5,7,9 };double array1[3] = { 1.2, 1.3, 1.4 };// 对象的初始化struct Person{ int id; double salary;}zhang3{ 1, 3000 };
在C++11中,列表初始化变得更加灵活了,来看一下下面这段初始化类对象的代码:
12345678910111213141516 ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. 模板的右尖括号在泛型编程中,模板实例化有一个非常繁琐的地方,那就是连续的两个右尖括号(>>)会被编译器解析成右移操作符,而不是模板参数表的结束。我们先来看一段关于容器遍历的代码,在创建的类模板Base中提供了遍历容器的操作函数traversal():
1234567891011121314151617181920212223242526272829// test.cpp#include <iostream>#include <vector>using namespace std;template <typename T>class Base{public: void traversal(T& t) { auto it = t.begin(); for (; it != t.end(); ++it) { ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在C++11中增加了很多新的特性,比如可以使用auto自动推导变量的类型,还能够结合decltype来表示函数的返回值。使用新的特性可以让我们写出更加简洁,更加现代的代码。
1. auto在C++11之前auto和static是对应的,表示变量是自动存储的,但是非static的局部变量默认都是自动存储的,因此这个关键字变得非常鸡肋,在C++11中他们赋予了新的含义,使用这个关键字能够像别的语言一样自动推导出变量的实际类型。
1.1 推导规则C++11中auto并不代表一种实际的数据类型,只是一个类型声明的 “占位符”,auto并不是万能的在任意场景下都能够推导出变量的实际类型,使用auto声明的变量必须要进行初始化,以让编译器推导出它的实际类型,在编译时将auto占位符替换为真正的类型。使用语法如下:
1auto 变量名 = 变量值;
根据上述语法,来列举一些简单的例子:
12345auto x = 3.14; // x 是浮点型 doubleauto ...