C++及计算机基础知识 - 03

1 静态数据成员

静态数据成员只能在外部初始化。

静态的好处就是,它与类的实例无关,不需要this指针,一切不需要实例化就可以有确定行为方式的函数都应该设计成静态的。对于某些设计模式如singleton,以及可以封装的方法,如Math::sin(),肯定比实例化一个math,然后math.sin()好用,这样还需要构造赋值等。

2 struct

如果有结构体Person,那么:

struct Person sister;

这种带struct的就是c风

Person brother;

不带struct的就是C++风格的。

3 _cdecl和_stdcall

_cdel是C Declaration的缩写,表示C语言默认的函数调用方法,所有参数从右至左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。

_stdcall是Standard Call的缩写,是C的标准调用方式,所有参数从右至左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是retn X,X表示参数占用的字节数,CPU在ret后自动弹出X个字节的堆栈空间,称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多或者少,否则会出错。

4 编译

编译分两步,第一步是将cpp和对应的h文件编译成obj文件,第二步是将所有obj文件进行链接,生成exe文件。对应的错误就是编译错误和链接错误两种,编译错误有语法错误等,链接错误有重复定义等。编译以cpp为单位,#include预编译指令就是单纯复制,把需要包含的文件的代码复制到当前文件。

每一个obj就是一个编译单元;常见到的pragma就是pragmatic缩写;函数的声明和定义默认都是extern的,即函数默认是全局的。static修饰的全局变量的声明和定义是同时进行的,即头文件中声明static全局变量的时候就定义了,多个地方引用静态全局变量所在的头文件,不会出现重定义的错误,因为每个编译单元都对它开辟了额外的空间存储。

链接把不同编译单元产生的符号联系起来,有内部和外部链接两种。

5 inl文件

内联函数,或者模板,避免头文件过大,版面混乱,将定义移动到单独的inl文件中,然后包含到类声明所在头文件的最后即可。inl中可以包含其他头文件,惯例命名为a.inl,a.h和a.cpp。

6 函数指针作为参数

函数指针原型:int (*myFuncVar)(int a, int b) ;    //本质是一种变量,专门用做指向函数,变量名为myFuncVar

  我们可以这样定义并赋值:

  int add();

  int (*myFuncVar)(int a, int b) = add;

7 虚继承

虚继承的目的是让某个类做出声明,承诺愿意共享它的基类,这个被共享的基类即虚基类。这样不论虚基类在继承体系中出现多少次,在派生类中都只包含一份虚基类成员。

8 std::function

类模板std::function是一种通用的多态函数包装器。std::function可以存储,复制和调用任何Callable 目标的实例- 函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针。示例如下:

template <class T>
T Add(T i, T j)
{
    return i + j;
}
 
int main()
{
    std::function<int(int, int)> f = Add<int>;
    f(2,3);
    return 0;
}

9 lambda

形式如下:

[函数对象参数] (操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}

示例如下:

[] (int x, int y) { return x + y; } // 隐式返回类型
[] (int& x) { ++x;  } // 没有 return 语句 -> Lambda 函数的返回类型是 'void'
[] () { ++global_x;  } // 没有参数,仅访问某个全局变量
[] { ++global_x; } // 与上一个相同,省略了 (操作符重载函数参数)

10 多线程 

notify_all表明状态变化,如果一个主线程任务完成,通知其余子线程开始执行,使得所有wait在条件变量上的子线程去竞争锁。notify_one通常用于资源可用,如单一生产者,一次生产一个,最好只有一个消费者去消耗,只唤醒一个wait在条件变量上的子线程,不竞争锁。

condition_variable使用要包含:

#include <condition_variable>

其wait方法会使当前线程等待,即阻塞,当被阻塞后,该函数会自动进行锁的unlock,即释放锁,从而让其他被阻塞在锁竞争上的线程继续执行。一旦当前线程获得通知,即其他线程调用notify_*,wait函数会自动调用lock方法,使得锁的状态和wait调用前相同。

11 内存分配

内存分配有三种:

静态存储区:内存在编译时已分配好,程序的整个运行期间都存在,如全局变量,static变量等。

栈上:局部变量在栈上创建,函数结束后被回收,效率高,容量有限。

堆上:malloc或者new申请的,任意大小,自己free或者delete。

已初始化的全局变量和局部静态变量保存在 .data段中,未初始化的全局变量和未初始化的局部静态变量保存在 .bss段中。

text是只读的,data和bss是可读可写的,bss是block started by symbol的缩写。

12 字符串数组元素个数

如数组名为a,则可以使用:

sizeof(a) / sizeof(a[0])

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值