- C++:#include指令,包含来自标准库的头文件时,用尖括号<>包围头文件名;对于不属于标准库的头文件,则用双引号""包围。对于<>,先去系统目录中找头文件,如果没有在到当前目录下找;对于"",首先在当前目录下寻找,如果找不到,再到系问统目录中寻找。
- C ++ 语言并未定义任何输入输出 ( IO ) 语句 , 取而代之 , 包含了一个全面的标准库( standard library ) 来提供 IO 机制 ( 以及很多其他设施 ) 。
iostream 库包含两个基础类型istream和 ostream , 分别表示输入流和输出流。
标准库定义了 4 个IO对象:
-
为了处理输入 , 我们使用一个名为 cin的 istream 类型的对象,这个对象也被称为标准输入 ( standardinput ) 。
-
对于输出 , 我们使用一个名为 cout的ostream 类型的对象, 此对象也被称为标准输出 ( standard output )。
-
标准库还定义了其他两个ostream 对象 , 名为 cerr 和 clog。我们通常用 cerr 来输出警告和错误消息 , 因此它也被称为标准错误 ( standard error ) 。
-
clog用来输出程序运行时的一般性信息。
-
std:
- 标准命名空间。
- C++标准库中的函数或者对象都是在命名空间std中定义的,所以我们要使用标准函数库中的函数或对象都要使用std来限定。
- 例如:使用 string 类型必须首先包含string头文件。作为标准库的一部分, string 定义在命名空间 std 中:
#include <string>
using std::string;
- 初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。
-
初始化
- 定义一个名为 num 的 int 变量并初始化为 0 ,有以下四种方式:
int num = 0;
int num = { 0 };
int num{ 0 };
int num(0);
用花括号来初始化变量的形式称为列表初始化,当用于内置类型(字符、整型、浮点数等)的变量时,这种初始化形式有一个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错:
long double num = 3.14;
int a = num;
cout << a << endl;//警告,输出3
int b = { num };
cout << b << endl;//报错
int c{ num };
cout << c << endl;//报错
int d(num);
cout << d << endl;//警告,输出3
return 0;
- 如果是内置类型的变量未被显式初始化,它的值由定义的位置决定。
- 定义于任何函数体之外的变量被初始化为 0。一种例外情况是 , 定义在函数体内部的内置类型变量将不被初始化。
- 一个未被初始化的内置类型变量的值是未定义的 ,如果试图拷贝或以其他形式访问此类值将引发错误。
- string类规定如果没有指定初始值则生成一个空串。
void Test()
{
int num;
cout << num;//报错
string str;
cout << str;//输出空串
}
-
extern:
- 当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去编译;
- 当它修饰变量时,如extern int i;则表示声明了一个变量,而不是定义。(定义:申请了存储空间,而且也可能为变量赋一个初值)
a.任何包含了显式初始化的声明即成为定义。(我们可以给由extern标记的变量赋一个初值,但是就抵消了extern的作用。)
b.在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误。
c.变量能且只能被定义一次,但可以被多次声明。(如果要在多个文件中使用同一个变量,就必须将声明和定义分离。此时,变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行声明,却绝对不能重复定义。)
extern int a;//声明a
extern int b = 10;//定义b
int c;//声明并定义c
void TestExtern() {
extern int d = 10;//错误
}
- 为一个已有的类型取一个新的名字。
- typedef 类型 别名;
- using 别名=类型;
#include <iostream>
using namespace std;
int main()
{
typedef int inter;
inter a = 1;
cout << a;
}
typedef int NewInt;
NewInt num = 20;
using _NewInt = int;
_NewInt num2 = 10;
-
枚举类型:
- 默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。但是,当给一个名称赋予一个值时,其后面的都会比前面一个名称大 1,但其前面的还是按默认0,1,2...赋值。
- C++:枚举类型中的每个元素,可以直接使用,不必通过类型.元素的方式调用
#include <iostream>
using namespace std;
enum testEnum
{
spring,
summer=5,
fall,
winter
} testc;
int main()
{
testc = spring;
cout << testc;//输出0
testc = fall;
cout << testc << endl;//输出6
}
3.C#:枚举类型中的每个元素必须通过类型.元素的形式调用
enum TestEnum
{
spring,
summer=5,
fall,
winter
}
private void Init()
{
TestEnum testEnum = new TestEnum();
testEnum = TestEnum.spring;
Debug.Log((int)testEnum);//输出0
testEnum = TestEnum.fall;
Debug.Log((int)testEnum);//输出6
}
【2020/05/25补充】
-
引用:&d(d是变量名)
- 引用为对象起了另一个名字,引用本身不是对象,不开辟内存单元。
- 引用必须初始化:定义引用时,程序把引用和它的初始值绑定在一起,而不是把初始值拷贝到引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另一个对象,所以引用必须初始化。
- 定义了一个引用后,对其进行的所有操作都是在与之绑定的对象上进行的。
- 为引用赋值,实质是把值赋给了与引用绑定的对象;获取引用的值,实际上是获取了与引用绑定的对象的值;以引用作为初始值,实际上是以与引用绑定的对象作为初始值。
- 大部分情况下,引用的类型要和与之绑定的对象严格匹配。
- 引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起。
int val1 = 10;
int &refVal1 = val1;//refVal1 是val1的另外一个名字。
int val2 = 20;
&refVal1 = val2;//报错,无法令引用重新绑定到另外一个对象。
int &refVal2;//报错,引用必须被初始化。
int val1 = 10;
int &refVal1 = val1;
refVal1 = 20;//把20赋值给refVal1绑定的对象,即val1;
cout << val1<<" "<< refVal1<<endl;//输出20 20
int val2 = refVal1; //获取refVal1的值,实际上是获取了val1的值。
cout <<val2<<" "<< val1 << " " << refVal1;//输出20 20 20
float timer = 20;
int &refTimer = timer;//报错,类型不同
int &refVal1 = 20;//报错,引用类型的初始值必须是一个对象
-
指针:*d(d是变量名)
- 指针本就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。
- 指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
- 指针存放某个对象的地址,要想获得该地址,需要使用取地址符(&)。
- 一般情况下,指针的类型要和它所指向的对象严格匹配。
- 如果一个指针指向了一个对象,则允许使用解引用符(*)来访问该对象。
int a = 10;
int *p1 = &a;//p1存放变量a的地址
int *p2 = p1;//p2存放p1,即存放变量a的地址
cout << *p1 << " " << *p2 << endl;//*解引用符,得到p1、p2所指的对象a,输出10 10
*p1 = 10;//*解引用符,得到p3所指的对象b,为变量b赋值。
cout << *p1 << " " << *p2;//*解引用符,得到p1、p2所指的对象a,输出10 10
int num = 10;
int &a = num;//&紧随类名出现,a是一个引用
int *p = &a;//*紧随类名出现,p是一个指针;
//&出现在一个表达式中,是一个取地址符
*p = 20; //*出现在一个表达式中,是一个解引用符,获得num对象
-
空指针:
- 得到空指针最直接的办法就是用字面值 nullptr 来初始化指针,nullptr是一种特殊类型的字面值, 它可以被转换成任意其他的指针类型。
- 任何非0指针对应的条件值都是true。
int *p = nullptr;//等价于int *p = 0;
int *p = 0;//直接将p初始化为字面常量0;
int *p = NULL;//等价于int *p = 0;
-
void* 指针:
- void* 是一种特殊的指针类型,可用于存放任意对象的地址。
- 不能直接操作void* 指针所指的对象,因为我们并不知道这个对象到底是什么类型,也就无法确定能在这个对象上做哪些操作。
int num = 10;
double d = 20;
void *v = #
v = &d;
- const :如果想在多个文件之间共享 const 对象,必须在变量的定义之前添加 extern关键字。(只在一个文件中定义 const ,而在其他多个文件中声明并使用它。)
【2020/05/26补充】
-
对指针的引用
格式:类型 *&指针引用名=指针;
int num = 10;
int *p = #
int *&q = p;
*q = 11;
cout << num << endl;//11
*p = 12;
cout << num << endl;//12
-
对常量的引用:
- 对常量的引用不能被用作修改它所绑定的对象。
- 不可以让一个非常量引用指向一个常量对象。
const int num = 20;
const int &refNum = num;
refNum = 30;//错误:不可以修改它所绑定的对象
int &refNum2 = num;//错误:不可以让一个非常量引用指向一个常量对象
-
指向常量的指针:
- 指向常量的指针不能用于改变其所指对象的值。
- 要想存放常量对象的地址,只能使用指向常量的指针。
- 指向常量的指针所指的对象不一定必须是个常量,仅仅要求不能通过该指针改变对象的值。
int num = 30;
const int *cNum = #
*cNum =20;//错误,指向常量的指针不能用于改变其所指对象的值。即:不能改变num的值
cout << *cNum;
const int num = 30;
int *cNum = #//错误:cNum是一个普通指针。
const int *cNum = #//正确
const int num = 30;
const int *cNum = #
int num2 = 20;
cNum = &num2;
-
const 指针:指针本身为常量
- 常量指针必须初始化,而且一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变了。
- 把 * 放在 const 关键字之前用以说明指针是一个常量。
- 指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全依赖于所指对象是否为常量。
- coust靠近谁谁就不能变;
- 一个比较好记的方法来区分 int const *p与 int* const p:把*读作pointer to然后从后往前读。
- int const *p就可以读作 p is a pointer to const int,p是指向常量的指针
- int* const p就可以读作 p is a const pointer to int,p是指向int型的常指针
int num = 30;
int *const cNum = #
*cNum = 20;//正确,指针指向的那个地址中的值可以变。
cout << *cNum;
int num2 = 20;
cNum = &num2;//错误:指针本身的值不能变
const int num = 30;
const int *const cNum = #//cNum是一个指向常量的常量指针
*cNum = 20;//错误,num为常量
int num2 = 20;
cNum = &num2;//错误:指针本身的值不能变
-
顶层const:
- 常量指针;
- 本身是常量:对任何数据类型都适用。
-
底层const:
- 指向常量的指针;
- 与指针和引用等复合类型的基本类型有关。
- 指针类型既可以是顶层 const 也可以是底层 const。
int num = 10;
int *const p1 = #//p1是常量指针,p1的值不可改,p1是顶层const
const int num2 = 20;//num2是整型常量,num2的值不可改,num2是顶层const
//指向常量的指针所指的对象不一定必须是个常量
const int *p2 = #//p2的值可改,p2是底层const
-
auto类型说明符:
- 让编译器通过初始值来推算变量的类型;
- auto定义的变量必须初始化。
auto num = 10;
num = "s";//错误,num是int类型,不能更改数据类型
-
decltype
- 选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值:
decltype(fun()) sum = x;//sum的类型就是fun()的返回类型
*编译器并不实际调用函数 fun ,而是使用当调用发生时 fun 的返回值类型作为 sum 的类型。