定义新量
auto 自动根据初始值的类型进行自动类型推导.
decltype 根据表达式的类型定义对象
右值引用, 操纵右值对象std::move()
, 可以将一个
枚举
不限定作用域的定义
enum color {red, green, blue};
限定在类型内部的作用域
enum class color {red, green, blue};color a = color::red
函数
数组传参的长度处理
- 直接传递数组长度
- 使用C风格字符串(默认结尾有标志)
- 使用C++11的新函数begin()和end()同时传递首尾地址
函数指针bool (*pf)(int, int)
可以指向bool max(int a,int b)
调用 pf(1, 1)
即可
常用于函数的参数是一个函数的返回值
Lambda[]() -> return type {statements}
中括号代表lambda引导, 其中的captures子句在同一作用域下lambda主体捕获(访问)哪些对象
以及如何捕获这些对象
- 可以为空, 不会访问外围对象
- [=] 代表用值捕获的方式
- [&] 代表引用捕获
类
辅助函数
定义辅助函数, 有点像Java里面的重写toString()函数(最常见的代表的例子)
ostream &print(ostream &os) |
友元函数
一个类的辅助函数从概念上可以看成类的接口, 虽然和类的关系很密切, 但并不是类的成员, 所以不能直接访问私有成员
C++ 中可以将该类函数声明为该类的友元.
这样就能访问到类的非公有成员.
在函数的前面加上friend
关键字
友元类
如果A想访问B的私有成员, 可以在B内声明friend class A
, 这样就可以在B内访问A的私有成员
友元关系是单向的, 不具有交换性, 同时也不具有传递性
构造函数
默认构造函数没有参数, 或者所有的参数都具有默认值
C++11允许在显示定义构造函数的情况下使用默认构造函数
需要在默认构造函数后面加上= default
使用默认构造函数创建类对象时, 切忌在对象名后I使用圆括号, 成了一个函数声明
初始值列表
T(int a, int b):a_(a), b_(b){}
引用和const修饰的必须用初始值列表初始化, 初始的顺序取决于数据成员在类内的定义顺序,
而非初始值列表的顺序
简化构造函数
实际将自己的带参构造函数, 给定默认值, 这样就实现了默认构造函数和带参构造函数的合并
复制构造函数
参数为该类的引用
委托构造函数
减少构造函数代码量
实际就是一个构造函数后面加上:
调用另一个构造函数, 同时传入参数
class A |
运算符重载
T operator /(A, B);
双目运算符两个参数
单目运算符一个参数
对于二元运算符, 左侧运算对象传递给第一个参数, 右侧运算对象传递给第二个参数.
运算符重载的声明和定义的分离
放在类成员中的运算符重载, 需要算入默认的this指针参数
// test.h |
类成员指针
数据成员指针 (private不能通过指针访问)
其值是数据成员所在地址相对于对象起始地址的偏移值
A T::*p1 = &T::x |
p1指向T类中的 A类型的x数据成员A T::
可以用auto
成员函数指针
int (A::*pf)(); |
统一初始化X x1 = {0} 和 X x2 {0}
这两种是不同的实现!!, 大多数情况下这两个是相通的, 然而当explicit构造函数
存在的时候前者的初始化是错误的
int x{0} int x= 0 int x(0)
最后一个是错误的可能会和函数声明冲突
class A |
另外还存在一个
std::atomic<int> a1{0}; // OK |
这个错误的原因是copy-initialization引起的
这个copy-initialization发生在T x = a
的声明, 下面我把原博客的部分重要英文替换成中文或代码描述std::atomic<int> a3 = 0
从int类型
赋值到可能是 cv-qualified
的class type
cv-qualified
// ***cv-qualified*** |
std::atomic<int> a3 = 0
满足了这个条件属于copy-initialization
copy-initialization
直接初始化和复制初始化的区别
直接初始化会直接用参数生成对象, 而复制初始化会用参数生成临时对象, 然后将这个对象复制到正要创建的对象
class A |
接下来需要通过std::atomic<int>(int)
把0转换成成一个纯右值(prvalue)的临时对象
纯右值
纯右值
然后再将这个临时对象用直接初始化(调用复制构造函数), 然而std::atomic<int>
把拷贝
构造函数给禁用了, 就会出错std::atomic<int> a3 {0}
这个会直接调用接收int的构造函数
回到X x1 = {0}
这里, 这个表达式是一个复制构造, 用一个braced-init-list(指的{0}).
这里有两个阶段
首先是会把单个参数的构造函数汇总起来(得到A-list)供选择, 如果其中没有合适的构造函数, 再将候选列表
转换为所有构造函数
如果如果A-list没有构造函数, 并且class T存在默认构造函数, 第一阶段就会被忽略
如果在一个使用{}
的初始化, 并且选择到了explicit 构造函数头上
就会报错
explicit
可以防止在调用某个成员函数的时候, 实参类型(通过构造函数之一)自动转换成相应参数,
但此时这个函数需要其他的成员变量参与到函数运行, 恰巧这时所需要的其他成员变量没有得到合适的初始化, 就会发生错误(没有得到合适初始化的原因就是, 自动调用了不合适的构造函数生成了这个函数所需要的参数(一般是对象))
@2019年10月26日21:25:58@算是第一次解决一个环环相扣的问题, 精力有点不足了
https://zhuanlan.zhihu.com/p/21102748 后续会继续进行理解
这里还发现一个
模板, 泛型 动态内存, 数据结构
template <typename T> |
C++堆的内存需要手动new和delete, 如果一个对象new出来没有在能被释放的时候释放就会造成–内存泄漏(需要及时delete不需要的对象)
一个指向动态内存的指针, 在动态内存被释放后, 指针依然指向原来的地址–空悬指针(释放内存后将相应的指针设置为nullptr)
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。