C++是一门编译型语言。源代码必须交由编译器处理生成可执行文件,然后由链接器组装成可执行程序。
一个可执行文件通常是为一个特定的硬件与操作系统组合而制定的,换句话说,它在安卓设备与Windows个人电脑之间是不可移植的,因此,可移植性指的是源代码的可移植性,即源代码可以在多种系统中编译成功,然后运行。
最小的C++程序:
int main(){}
定义一个main函数,不接受任何参数,也不做任何事情。
//旧版本
#include
int main() {
std::cout << "Hello, World!\n";
}
//C++20版本
import std;
int main() {
std::cout << "Hello, World!\n";
}
import std;
指示编译器去声明标准库变量的存在。如果没有这个声明,std::cout << "Hello, World!\n";
将没有意义。但是指令import将所有标准库放进一个单独的std模块还没有成为标准。
double get(const vector& vec, int index);
//函数类型是:
double(const vector&,int)
对于成员函数来说,类的名称也是函数类型的一部分:
char& String::operator[](int index);
//函数类型是:
char& String::(int)
可以引入单引号(’)作为数字分隔符提升长字面量的可读性
例如:Π的值大约是:3.14159 ‘ 26535 ’ 89793 ‘ 23846 ’ 26433 ‘ 83279 ’ 50288
用十六进制表示就是:0x3.243F ’ 6A88 ‘ 85A3 ’ 08D3
部分操作符的计算顺序是从左向右的:
x.y、x->y、x(y)、x[y]、x<
但赋值符号的计算顺序是从右往左的:
x += y
double d1 = 2.3;
double d2 {2.3};//等价于double d2 = {2.3}
int i1 = 7.8;//i1变成了7(你可能感到意外)
int i2 {7.8};//错误:floating-point to integer conversion
如果变量的类型可以从初始化符号中推导出来,就无需显示指定类型
auto b = true; //bool类型
auto ch = 'x'; //char类型
auto i = 123; //int类型
auto d = 1.2; //double类型
...
使用auto声明变量时,作者倾向于使用=符号,因为没有类型转换的风险。当然,偏好使用{}也无伤大雅。
当没有明显的需要显示地指定类型时,一般使用 auto 。
理由如下:
某些对象也可以没有名字,比如:临时对象或者用new创建的对象:
vector vec; //vec是全局名字(全局整数动态数组)
void fct(int arg) { //fct是全局名字(全局函数)arg是局部名字(局部整数参数)
string motto {"Who dares wins"};//motto是局部名字
auto p = new Record{"Hume"}; //p指向无名Record对象(由new创建)
//...
}
struct Record {
string name; //name是Record的成员名字(字符串成员)
//...
};
一个new创建的对象可以持续“生存”,知道用delete将其销毁。
C++支持两种不变性:
例如:
constexpr int dmv = 17; //dmv是一个命名常量
int var = 17; //var不是常量
const double sqv = sqrt(var); //sqv是一个命名常量,可能在运行时计算
double sum(const vector&); //sum不会修改它的参数
vector v {1.2, 3.4, 4.5}; //v不是常量
const double s1 = sum(v); //可行:sum(v)在运行时计算
constexpr double s2 = sum(v); //错误:sum(v)不是一个常量表达式
为了使函数可在常量表达式中使用,这个函数必须被定义为constexpr 或consteval,这样才能在编译期表达式中被计算。
例如:
constexpr double square(double x){return x*x};
constexpr double max1 = 1.4*square(17); //可行:1.4*square(17)是常量表达式
constexpr double max2 = 1.4*square(var);//错误:var不是常量,所以square(var)不是常量
const double max3 = 1.4*square(var); //可行:允许在运行时计算
在声明中,[ ]
意味着对应类型的数组,*
意味着指向对应类型的指针。
char v[6]; //6个字符组成的数组
char *p = &v[3];//p指向v的第4个元素
char x = *p; //*p代表p指向的对象
*
表示取内容,前置一元操作符&
表示取地址,后置一元操作符&
表示指向前者的引用。&
、*
、[ ]
被称为声明操作符。T* p //T*:p是一个指向T的指针
T& r //T&:r是一个指向T的引用
T f(A) //T f(A):f是一个函数,接受A类型的参数,返回T类型的结果
当确实没有对象可指向,我们希望表达出一种“没有对象可用”的含义时,可令指针取值为nullptr。所有指针类型共享同一个nullptr。
在使用指针前检查它是否为空,是明智的行为:
int count_x(const char* p, char x){
//计算x在p[]中出现的次数
//假定p指向一个以零结尾的字符数组(或者指向空)
if(p == nullptr)
return 0;
int count = 0;
for(; *p != 0; ++p)
if(*p == x)
++count;
return count;
}