【侯捷 C++标准11】课程笔记以及个人注释(附带课程资源)

前言

上周我们学习了【侯捷 C++ 面向对象高级开发】课程笔记以及个人注释(附带课程资源)

趁热打铁,继续学习。

这个系列教程主要讲述了Cpp11和14的新特性,只谈新东西。

这个教程我之前摸索学习了大概几节课,现在重新系统学习一下。

该课程笔记会记录我认为所有重要的、有用的知识点。

重要说明:

  1. 侯捷老师说得非常好,十分详细,一定要自己看看才可以知道我这个笔记在说什么。
  2. 很多东西我觉得比较泛用,如auto,range-based for,我就没有记下来。

课程资源

源自公众号:编程指北

链接: https://pan.baidu.com/s/19REVrk-_3lpQu_fUmRBRUw 密码: 7iup

或有条件也可以直接访问Youtube资源。


篇1 可变模板 Variadic Templates

之前学过。这种很方便做recursive function call,也可以方便进行recursive inheritance(如tuple)

  1. 多个重载版本的函数,会根据参数类型、顺序来调用。类型和顺序都很重要,要同时符合。
  2. 这里后面讲了很多细节,暂时没遇到,就先不写了。
//无参函数,可能是不需要的
void printX() {

}

//泛化的函数
template <typename T,typename... Types>
void printX(const T& firstArg, const Types&... args) {
	cout << firstArg << endl;
	//cout << sizeof...(args)<<endl; //包的大小
	printX(args...); //一包输出
	
}

//更泛化的函数
template<typename... Types>
void printX(const Types&... args) {

}


int main() {
	printX("hello", "chenliang", "liang",180);
	return 0;
}

篇2 一致性初始化 Uniform Initialization

{}来一致性初始化,是一个通用的语法。编译器会做一个initializer_list,会关联(通过指针)到一个array<T,n>,T是类型,n是大小。但是需要初始化的类型支持{}来一致性初始化。

	int values[]{ 1,2,3 };
	vector<int>v{ 2,3,3 };

如果使用空的{},则会有默认初值,如0或者nullptr。但记住,它不允许narrowing initializations!,如int x{5.3}会报错。


篇3 初值列表 Initializer Lists

可作为函数的参数,可变参数,但必须是统一类型了。同时也可以作为构造函数。

比显示说明参数数量的更泛化一点。


篇7 Explicit for ctors taking more than one argument

多个参数要求explicit,即不可隐式转换(甚至不可以从initializer list去隐式转换)。

当然我们可以从one argument开始理解。

Explicit for ctors taking only one argument

禁止隐式转换,上个课程有。

Class Complex{
    
    explicit
    Complex(int re,int im=0):....{....}
}

Complex c1(12,5);
Complex c2 = c1 + 5; //如果没有explict,则可以

篇9 =defualt, = delete

如果没有定义构造函数,那么编译器会自带一个默认构造函数,**但是如果自己定义了,默认构造函数就会丢掉。**如果我们还是希望保留,则用=defualt来显式保留,但用=delete显式删除。

class Zoo {
public:
	Zoo(int i1, int i2) :d1(i1), d2(i2) {}
	Zoo(const Zoo&) = delete;
	Zoo(Zoo&&) = default;
	Zoo& operator = (const Zoo&) = default; //copy
	Zoo& operator = (const Zoo&&) = delete; //move
	virtual ~Zoo() {}
private:
	int d1, d2;
};

注意:如果类中包含了一个指针,则一般需要自己写BIG THREE。

No-Copy and Private-Copy

这里跟Effetivre C++讲的一样。

No-Copy(完全去掉了构造函数、赋值构造之类的函数)完全不能copy,PrivateCopy(把构造函数放在了private部分)可以被友元以及子类copy。


篇10 别名模板 Alias Template

使用using关键字建立一个别名类型,以免类型十分赘余。

注意:别名无法做特化。

template <typename T>
using Vec = vector<T,MyAlloc<T>>;

Vec<int> coll; //它等于vector<int,MyAlloc<int>>;

这里视频讲得很深,我没感受到有什么用,就不拓展了。


篇12

Type Alias

类型的别名

using func = void(*)(int,int);

noexcept

设计者需要保证某个函数不会丢出异常。

noexcept(条件),即条件满足的情况下不会丢出异常。

void swap(x,y) noexcept(noexcept(x.swap(y))){
    x.swap(y);
}

override

实现父类的虚函数,显式写出覆盖的语句声明。

final

跟java一样,不希望类或者方法继承,可以加final关键字。


篇13 decltype

获得一个变量的type。目前看不出来还有什么用。


篇14 lambda

是inline函数,是很实用的东西。

[x,&y(即传值还是传引用)](参数)mutable(决定引用的是否可以改变) throw -> returnType{...}


承上启下

上面讲了语言特性,以下讲标准库特性。


篇 23 Rvalue references and Move Semantics

右值引用,是一种新的引用类型,避免unnecessary copying。当赋值右手边为rvalue,赋值左手边的值可以通过steal来获取rvalue的值,而不需要内存分配。

  • Lvalue: 可以出现在operator =左侧者。
  • Rvalue:只能出现在operator=右侧者。

篇25 写一个move-aware class

很好的一个例子。

class MyString {
public:
	static size_t DCtor; //累计default-ctor呼叫次数
	static size_t Ctor;	//累计ctor呼叫次数
	static size_t CCtor; //累计copy-ctor呼叫次数
	static size_t CAsgn; //累计copy-asgn呼叫次数
	static size_t MCtor;  //累计move-ctor呼叫次数
	static size_t MAsgn;  //累计move-asgn呼叫次数
	static size_t Dtor;  //累计dtor的次数
private:
	char* _data;
	size_t _len;
	void _init_data(const char* s) {
		_data = new char[_len + 1];
		memcpy(_data, s, _len);
		_data[_len] = '\0';
	}
public:
	//default constuctor
	MyString() :_data(nullptr), _len(0) { ++DCtor; }

	//constructor
	MyString(const char* p) :_len(strlen(p)) {
		++Ctor;
		_init_data(p);
	}

	//copy constructor
	MyString(const MyString& str) :_len(str._len) {
		++CCtor;
		_init_data(str._data);
	}

	//move constructor
	MyString(MyString&& str) noexcept
		:_data(str._data), _len(str._len) { //直接使用原来的指针
		++MCtor;
		str._len = 0;
		str._data = nullptr;
	}

	//copy assignment
	MyString& operator=(const MyString& str) {
		++CAsgn;
		//自我赋值检查
		if (this != &str) {
			if (_data) delete _data;
			_len = str._len;
			_init_data(str._data);
		}
		return *this;
	}

	//move assignment
	MyString& operator=(MyString&& str) noexcept {
		++MAsgn;
		//自我赋值检查
		if (this != &str) {
			if (_data) delete _data;
			_len = str._len;
			_data = str._data;//直接使用原来的指针
			str._len = 0;
			str._data = nullptr;
		}
		return *this;
	}

	//dtor
	virtual ~MyString() {
		++Dtor;
		if (_data) {
			delete _data;
		}
	}
};
size_t MyString::DCtor = 0;
//...

后话

这里的知识普遍比较高级,实用性可能没有上一节课强,作为知识补充很不错。

看到这里基本算是cpp基础以及cpp11入门了,后面我将实际切入到项目当中进行学习。

欢迎留言交流,也欢迎私信交流。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值