1.注释界定符不能嵌套:
/*
*注释对/* */不能嵌套
*“”不能嵌套“”几个字会被认为是源码,像剩余程序一样处理
*/
最好的方式是用单行注释方式注释掉代码段的每一行
2.在循环次数已知情况下,for循环的形式显然更为简洁;
而循环次数未知时候,用while循环实现更为合适,用特定的条件控制循环是否执行,循环体中执行的语句可能导致循环判定实现条件发生变化
3.一般情况下,请不要在同一个表达式中混合使用无符号类型和带符号类型。因为计算前带符号类型会自动转换成无符号类型,当带符号类型取值为负就会出现异常结果。
unsigned u =10,u2=42;
cout<< u-u2<<endl;//10-42+2^32=4294967264
10e-2 = 10*10^(2)
x4d-(字符M) \12-(换行符) \0-(空字符)
#include <iostream>
using namespace std;
int main0201()
{
long double ld = 3.1415926536;
int a{ ld }, b = {ld};//错误 1 error C2397: 从“long double”转换到“int”需要收缩转换
int c(ld), d = (ld);//警告 3 warning C4244: “初始化”: 从“long double”转换到“int”,可能丢失数据
cout << a << "\t" << b << "\t" << c << " " << d << endl;
//cin >> int input_value;
//输入运算符的右侧需要一个明确的变量名称,而非定义变量的语句
int i = {3.14};
//引发警告,试图通过列表初始化的方式,是一种不被建议的窄化操作
//double salary = wage = 9999.99;
//声明多个变量时,需要用逗号将变量名隔开,而不能直接用赋值运算符连接
double salary, wage;
salary = wage = 9999.99;
int i = 3.14;//引发警告,试图通过列表初始化的方式,是一种不被建议的窄化操作
system("pause");
return 0;
}
/*
对于string 类型的变量来说,因为string类型本身接受无参数的初始化方式。
所以不论定义在函数体内还是函数外,都被默认初始化为空串
对于内置类型int来说,变量global_int 定义在所有函数体之外,根据c++规定,global_int默认初始化为0
而变量local_int定义在main函数的内部,将不被初始化,如果程序试图拷贝或者输出未初始化的变量,将遇到一个未定义的奇异值
建议初始化每一个内置类型的变量
当用于内置类型的变量时候,如果我们用列表初始化且初始值存在丢失信息的风险,则编译器报错
*/
string global_str;
int global_int;
void main()
{
int local_int;
string local_str;
}
4.c++标识符
由字母,数字和下划线组成,其中必须以字母或下划线开头,标识符的长度没有限制,但是对大小写字母敏感
同时,c++也为标准库保留一些名字 用户自定义的标识符不能连续出现两个下划线,也不能以画线紧连大字字母开头。定义函数体外的标识符不能以下画线开头
5.引用并非对象,相反,它只是为一个已经存在的对象所起的另外一个名字,引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起。
6.指针:在声明语句中的指针的类型实际上被用于指定它所指对象的类型,所以二者必须匹配,如果指针指向另一个其他类型的对象,对该对象的操作将发生错误
搞清楚一条赋值语句到底是改变了指针的值还是改变了指针所指对象的值不太容易,最好的方法就是记住赋值永远改变的是等号左侧的对象:
pi = &val;//pi的值被改变,现在pi指向了val 改变了那个存放在pi内的地址值
*pi = 0;//指针pi没有改变,*pi-指针pi所指的那个对象发生改变
任何非0指针对应的条件值都是true
7.void*指针能做的事情比较有限,1.拿他和别的指针做比较 2. 作为函数的输入或输出,3.赋值给另外一个void*指针
不能直接操作void*所指的对象,因为不知道这个对象到底是一个什么类型
void main0203()
{
int i = 3, j = 10;
/*
变量的声明定义:
extern int i;//声明i而非定义i
int i;//声明并定义了i
extern double pi=12.22;//定义
*/
int *p = &i;
cout << p << " " << *p << endl;
p = &j;
cout << p << " " << *p << endl;
*p = 20;
cout << p << " " << *p << endl;
j = 30;
cout << p << " " << *p << endl;
system("pause");
}
//2.22
void main()
{
int i = 0;
int *p1 = nullptr;//等价于int *p1=0;int *p1=NULL 空指针- 不指向任何对象
int *p2 = &i;
/*
判断指针p,指向的是不是一个合法的对象,只需要把p作为if语句的条件即可,合法条件为真,反之为假
*/
if (p1)//检查指针的值(指针所指的对象的地址)
{
cout << "p1 pass" << endl;
}
if (p2)//检查指针的值(指针所指的对象的地址)
{
cout << "p2 pass" << endl;
}
if (*p2)//检查指针所指对象的值
{
cout << "p2 pass" << endl;
}
system("pause");
}
int* p1,p2;//p1是指向int指针,p2是int,基本数据类型是int而非int*,*仅仅是修饰了p1
复合类型的声明:尽量采取将* (&)与变量名写在一起,以免产生歧义
指针和const:
指向常量的指针不能用于改变其所指对象的值
const double pi=3.14;//pi是个常量,它的值不能改变
double *ptr=π//错误,ptr是一个普通的指针
const double *cptr=π//正确,cptr可以指向一个双精度常量
*cptr=42;//错误,不能给*cptr赋值,因为cptr指针指向的是pi的地址,其中存储是pi,pi是常量,不过改变
const int &const p1;//非法,引用的本身不是对象,不能让引用恒定不变
int &r=0;//非法,非常量引用不能引用字面值常量0
const int &r=0;//合法,r是一个常量引用,可以绑定到字面值常量0
常量引用,常量指针,指向常量的指针区别:
int * const cp;//非法 cp是一个常量指针,其值不能被改变,所以必须初始化
常量指针-不变的是指针本身的值而非指向的那个值
常量的引用:
const int ci=10;
const int &r1=ci;//正确,引用及其对应的对象都是常量
r1=42;//错误 r1是对常量的引用
int &r2=ci;//错误,不允许直接为ci赋值,当然不能通过引用去改变ci,因此对r2的初始化时错误,假设该初始化合法,则可以通过r2改变他引用对象的值,显然不对
const int ic,&r=ic;//ic是一个常量,值不能被改变,所以必须初始化
const int *const p3;//p3是一个常量指针,其值不能被改变,所以必须初始化,同时指向的内存空间是一个常量,我们不能通过p3改变所指对象的值
const int *p;//但是p没有指向任何实际的对象
顶层const-表示指针本身是一个常量
底层const-表示指针所指的对象是一个常量
两者对于拷贝操作影响:2.31
int null=0,*p=null;
null是一个int变量,p是一个int指针,二者不能直接绑定,可修改为
int null =0,*p=&null;
实际:int null=0,*p=nullptr;
auto类型说明符:编程时候,常常需要把表达式的值赋值给变量,这就要求在声明变量的时候清楚的知道表达式的类型,故引入auto类型说明符,用它就能让编译器就替我们分析表达式所属的类型
auto i=0,*p =&i;//正确,i是整数,p是整型指针
auto sz=0,pi=3.14;//错误,使用auto能在一条语句中声明多个变量,因为一条语句,只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样
非常量引用不能绑定字面值:auto &h=42; 常量引用可以绑定字面值:const auto &j=42;
定义模板函数时,用于声明依赖模板参数的变量类型。
模板函数依赖于模板参数的返回值