解读王垠的文章:
首先我们具有下面这样的一个结构:
struct Point{
double x;
double y;
double getX() { return x;}
double getY() { return y;}
}
那么用户的代码为:
var x = Point.getX();
var y = Point.getY();
重新定义:
struct Point {
double r;
double angle;
double getX() const { r * cos(angle);}
double getY() const { r * sin(angle);}
};
那么用户的代码为:
var x = Point.getX();
var y = Point.getY();
关于一些软件的一些使用痛点:
- 使用一些所谓的xml,yaml文本格式, 具有一些复杂的缩进导致配置完全不清晰, 同时这些配置文件的清晰性不够好, 导致配置信息异常难读,
- 使用一些json文件的配置也是不够方便的
- 不要去使用一些DSL去做事情, DSL往往是不靠谱的, 它的逻辑也是不清晰的
为什么有需要基础的数据类型呢?这是因为出于计算逻辑和可读性的考虑
- 首先出于计算考虑, 我们需要使用一些数number进行计算
- 我们需要string来显示出来
- 我们需要布尔类型进行逻辑判断
基于这种值的设计我们可以将它放到各种适配的管道中进行传递, 然后基于这种管道我们可以封装出任意的函数模版, 基于函数模版我们可以构造出函数实例, 也就是闭包;
到这里一门编程语言的设计也就完成了。
每一个函数中都被绑定了一个this, 引用, 这个this引用指向当前的对象,
引用传递语法:
obj.x();
这个一个表达式, 这个表达式有四个部分组成,
- 首先是obj,这是一个对象
- 属性存取运算符
.
()
这也是一个运算符号
对象方法调用的时候, 函数__x()__
是来自于obj.x这个引用的, 所以这个引用将obj这个对象传递给x()
这才让函数_x()_
内部可以通过this来访问到obj
RAII是一种惯用法,把资源的有效期跟持有资源的对象的生命周期绑定到一起。它靠构造函数来完成资源的分配,并利用析构函数来完成资源的释放
好问题。静态存储区既不是堆也不是栈,而是……静态的。意思是,它们是在程序编译、链接时完全确定下来的,具有固定的存储位置(暂不考虑某些系统的地址扰乱机制)。堆和栈上的变量则都是动态的,地址无法确定。
thread_local和静态存储区类似,只不过不是整个程序统一一块,而是每个线程单独一块。用法上还是当成全局/静态变量来用,但不共享也就不需要同步了。
非静态数据成员加上动态类型所需的空间。注意后者不一定是4,而一般是指针的大小,在64位系统上是8字节。还有,要考虑字节对齐的影响。静态数据成员和成员函数都不占个别对象的空间。
在 C++ 里,所有的变量缺省都是值语义——如果不使用 * 和 & 的话,变量不会像 Java 或 Python 一样引用一个堆上的对象。对于像智能指针这样的类型,你写 ptr->call() 和 ptr.get(),语法上都是对的,并且 -> 和 . 有着不同的语法作用。而在大部分其他语言里,访问成员只用 .,但在作用上实际等价于 C++ 的 ->。
在 C++ 里,用 Obj obj; 这种方式定义的对象,在函数里就是栈上分配,在函数外就是静态分配。不会堆上分配
如果用new申请了一段动态内存,但是在程序中没有用delete进行释放,那么当程序执行结束时,这段动态内存是否会被释放呢?如果会的话,是由谁释放的呢?