-
cin 和 cout 分别是 ostream 和 istream 的对象,是内置对象,是由标准库的开发者提前创建好的。
-
endl 表示换行,功能等同于 “\n”。
-
C语言中 const 全局变量的可见范围是整个程序,在其他文件中使用 extern 声明后就可以使用;而C++中 const 全局变量的可见范围仅限于当前文件,在其他文件中不可见,所以它可以定义在头文件中,多次引入后也不会出错。
-
C++又新增了两个关键字,new 和 delete:new 用来动态分配内存,delete 用来释放内存。和 malloc() 一样,new 也是在堆区分配内存,必须手动释放
int *p = new int; //分配1个int型的内存空间
delete p; //释放内存
- new 操作符会根据后面的数据类型来推断所需空间的大小。如果希望分配一组连续的数据,可以使用 new[],用 new[] 分配的内存需要用 delete[] 释放,它们是一一对应的。
int *p = new int[10]; //分配10个int型的内存空间
delete[] p;
- C++规定,默认参数只能放在形参列表的最后,而且一旦为某个形参指定了默认值,那么它后面的所有形参都必须有默认值。
float d = 10.8;
void func(int n, float b=d+2.9, char c='@'){
cout<<n<<", "<<b<<", "<<c<<endl;
}
- 使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。
-
使用初始化列表来初始化字段 Line::Line( double len): length(len)。
- 一个派生类继承了所有的基类方法,但下列情况除外:
- 基类的构造函数、析构函数和拷贝构造函数。
- 基类的重载运算符。
- 基类的友元函数。
-
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
-
您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
virtual int area() = 0;
= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。
-
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
- 默认情况下,在类中定义的所有项目都是私有的。
- C++ 接口是使用抽象类来实现的。
- 如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。
- 抽象类不能被用于实例化对象。
-
抽象类的子类必须实现每一个虚函数。
-
new 与 malloc() 函数相比,其主要的优点是,new 不只是分配了内存,它还创建了对象。
- 我用g++编译器发现C++ 检查数组越界。
const
- int get() const{return i;} //get函数返回i的值,不需要对i进行修改,则可以用const修饰。防止在函数体内对i进行修改。
-
const成员函数是不能修改数据成员的,所以在const成员函数内只能调用const函数。
- const修饰的函数参数是指针时,代表在函数体内不能修改该指针所指的内容,起到保护作用。
//保护源字符串不被修改,若修改src则编译出错。
void fun(const char * src, char * des)
{
strcpy(des,src);
}
- # 和 ## 运算符,#处理成字符串,## 连接作用
C++ 信号处理
信号 | 描述 |
---|---|
SIGABRT | 程序的异常终止,如调用 abort |
SIGFPE | 错误的算术运算导致,比如除以 0 |
SIGILL | 检测到非法指令 |
SIGINT | 程序终止(interrupt)信号 |
SIGSEGV | 非法访问内存 |
SIGTERM | 发送到程序的终止请求 |
- 从 C++ 17 开始,auto 关键字不再是 C++ 存储类说明符,且 register 关键字被弃用。
static 关键字作用
- 声明静态局部变量
- 声明全局变量时限制作用域为本文件。
- 修改类成员变量时,所有对象共享。
- 使用 thread_local 说明符声明的变量仅可在创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。
隐式调用,声明类直接复制,等于隐式调用对应构造函数。 加上关键字 explicit 可以禁止隐式调用。
Apple apple = 10;// 隐式调用Apple(int size)
explicit Apple(int size);//禁止隐式调用
C++ 中 class 和 struct 的区别
- 默认的继承访问权限。class是 private ,struct 是public 。
- class 和 struct 可以相互继承。
-
使用哪种权限取决于子类。子类是 class 继承 struct 是private 继承。struct 继承 class 就是 public 继承。总之子类是 class 不管父类是什么,都是private 继承。子类是struct 不管父类是什么都是public继承。 这是默认的权限。也可以显式指定是 public 、 protected 和 private。
- 默认的数据访问权限。struct 是 public 的。 class 是private 。
-
也就是说类成员定的时候如果不显式指定访问权限。class的所有数据成员都是private 。struct所有的都是public。
- 可以将程序里所有的class全部替换成struct,它依旧可以很正常的运行。
- struct 是数据局结构的实现。class是对象的实现。建议当你设计的东西像数据的时候用struct。如果像对象的话用class。
-
“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。
- 默认浮点数常量类型是 double 占 8字节。如想要节省4字节就在末尾加f 变成 float。
- 默认整形常量是 int 占 4字节。可以末尾加 L 变成 long。
-
When building 32-bit applications, NSInteger is a 32-bit integer. A 64-bit application treats NSInteger as a 64-bit integer.
- 字节对齐指令 #pragma pack(1),表示 1 字节对齐。默认对齐字节数等于CPU位数。
x86_64 和 arm64的地址空间。
- x86_64 栈顶 0x7f+后面12位,堆 0x1+后面8位。地址空间 0 ~ 0x7fff8个f。地址空间是 47 位。
-
arm64 栈顶 0x1+后8位。堆 0x2+后面8位。地址空间是 36 位。
-
后三位都有特殊用处。
- static_cast 类型转换
- 外部类可以调用内部类的构造方法。
变长结构体。使用0长度数组。
- 长度为0的数组的主要用途是为了满足需要变长度的结构体。
- 数组名只是一个地址常量。数组长度可以动态指定。
子类构造函数
只有在没有显式声明构造函数的时候,编译器才会创建一个默认的构造函数。
子类想要初始化从父类继承的成员变量,需要调用父类的构造函数。
-
如果父类没有声明构造函数。即只有编译器创建的默认构造函数。此时子类的构造函数可以写成任意形式,有参或无参,不用管父类的构造函数。创建子类时,会先调用父类的默认构造函数,再调用子类构造函数。
-
如果父类只声明了无参构造函数。则子类可以显示也可以隐式调用父类的构造函数。
-
如果父类只声明了带参构造函数并且没有给参数设定默认值。则子类必须显示调用父类构造函数。
在子类构造函数后面加冒号然后跟上父类构造函数,就是显示调用父类构造函数。此时如果子类有和父类同名的数据成员。则会初始化子类的成员。
2022年04月17日更新
- std::move
用于将把参数转成右值引用,等于强制类型转换 static_cast<T&&>(arg),这样再把返回值传给容器的时候可以调用对象的移动构造函数。移动构造函数接收一个右值引用,并将参数对象的指针成员指向的内容赋值给新对象,而不是重新生成一份,节省内存开销,主要用于临时对象的传递。
- std::forward
template<class A>
void G(A &&a) {
F(std::forward<A>(a)); // 调用 F(A&& a)
F(a); // 调用 F(A& a)
}
从用户的角度来看,其含义std::forward是有条件地强制转换为右值。如果我编写的函数期望参数中包含左值或右值,并且仅当将其作为右值传递时,希望将其作为右值传递给另一个函数,则该功能很有用。如果我没有将参数包装在std :: forward中,它将始终作为常规引用传递。