当赋给带符号型一个超出它表示范围的值时,结果是未定义。
当赋给无符号型一个超出它范围的值,结果是初始值对无符号型表示总数取模后的余数。把-1赋给8比特(0~255)的unsigned char结果255
切勿混用带符号类型和无符号类型。
如果一个字面值连与之关联的最大的数据类型都放不下,将产生错误。
初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,二赋值的含义是把对象当前值擦除,而以一个新值来替代。
int i =0 ; int i = int i (0); int i; 初始化。
花括号是列表初始化。当用于内置类型的变量时,这种初始化形式有一个重要的特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编辑器将报错:
long double ld=3.1415926536;
int a,b=; 错误。
int c(ld),d=ld; /数据丢失。
如果定义内置变量类型未被显示初始化,他的值由定义位置决定:定义于任何函数之外的变量被初始化为0;定义在函数体内的内置类型将不被初始化。
如果想声明一个变量而不定义,就柱塞变量名前加extern,而且不要显示的初始化。
extern int i;//声明不定义。
int j ; 声明并定义。
extern double pi=3.14 ;/定义。
在函数内部,如果试图初始化一个由extern标记的变量,将引发错误。
标识符以字母或下划线开始,c++中标识符中不能连续出现两个下划线,也不能以下划线紧连大写字母开头。定义在函数体外的标识符不能以下划线开始。
引用一定要在定义是初始化,绑定。
因为引用不是对象,所以不能定义引用的引用。
引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起。
指针的值(4种):对象,指向紧邻对象所占空间的下一个位置,空指针,无效指针。
void*指针能做的事有限:和其他指针比较、作为函数的输入输出。或赋给另一个void*指针不能直接操作void*所指的对象,,不知道这个对象时什么类型。
int *&i=p;指向指针的引用(从右向左读)
利用一个对象去初始化另一个对象,则它们是不是const无关紧要:
int i = 43;
const int ci=i;
int j =ci;
如果想要在多个文件之间共享const对象,必须在变量的定义之前添加extern,来指明变量的定义在别处出现。定义时,加extern说明可以使其被其他文件使用。
extern const int bufsize=fcn();
extern const int bufsize;
对常量的引用(常量引用):
const int ci=123;
const int &r=ci;
r=24; /错。
int &r2=ci //错,试图让一个非常量引用指向一个常量对象。
引用的类型必须与所引用的对象的类型一致,但是有两个例外:
在初始化常量引用时允许用在任意表达式作为初始值,只要可转换,int i=3;
const int &r1 = i; /允许将const int&绑定到一个普通 int对象上。
const int &r2 = 34; /正确,r2是一个常量引用。
const int &r3 = r1 * 2; /正确,r3是一个常量引用。
int &r4=r1*2错,r4是一个普通的非常量引用。
在绑定应用时,double dval = 2;
const int&ri = dval;
此处将生成临时量(临时对象);
const int temp = dval;
const int &ri = temp;
对const的引用可能引用一个非const的对象。
常量引用仅是对引用可参与的操作做出了限制,对引用的对象本身并么有限定。所以可以通过其他途径改变。
const int* i;//指向常量的指针。
int*const i=j; /常量指针必须初始化。
顶层const(指针是一个const):
int i = 0;
int * const p1=&i; /不能改变p1的值,这是一个顶层const
const int ci= 42; /不能改变ci的值,这是一个顶层const
const int *p2=&ci; /允许改变p2的值,这是一个底层const
const int *const p3=p2;
const int &r = ci;//用于声明引用的const 都是底层const
i = ci;//正确,拷贝ci的值,ci是一个顶层const,对此操作无影响。
p2 = p3; /正确,p2和p3指向的对象相同,p3顶层const的部分不受影响。
int *p = p3;//错,p3包含底层const的定义,而p没有。
p2 = p3; /正确,p2和p3都是底层const
p2 = i; /正确,int*能转换成 const int *
int &r = ci; /错,普通int& 不能绑定到int常量上。
const int &r2 = i; /正确,const int& 可以绑定到一个普通 int 上。
用常量表达式初始化的const对象也是常量表达式。
constexpr声明,以便由编译器来验证变量的是否是一个常量表达式,声明为constexpr的变量一定是常量,而且必须使用常量表达式初始化。
一般来说,如果你认定变量是一个常量表达式,那就把它声明成constexpr类型。
常量表达式的值要在编译时计算,字面值类型,比较简单。
一个constexpr指针的初始值必须是nullptr或0,或是存储于某个固定地址中的对象。
函数体内定义的变量一般不是存放在固定地址中,不能用constexpr指针。
而在所有函数体之外的对象其地址不变,能用来初始化constexpr指针。
还有允许函数定义一类有效范围超出函数本身的变量,这类变量也有固定的地址。
constexpr引用也能绑定到这类变量上。
constexpr限定符仅对指针有效,与指针的对象无关:
constexpr int* q=nullptr; /q是一个指向整数的常量指针。
constexpr const int *p = i;//p是常量指针,指向整型常量。
别名声明。typedef double wages;
using si=int;
将表达式赋值给变量时,无法知道表达式类型,可以用auto,编译器会自己推算。
使用auto时如果一条一句中声明两个变量,俩个类型必须一样。
对于引用类型,auto出的是被引用的对象。
auto 一般不会保留顶层const,底层的会保留底层const
int i=0;
const int ci = i, &cr = ci;
auto b=ci; /b是一个整数。
auto c=cr;//c是一个整数,对于引用类型,auto出的是被引用的对象。
auto d=&i;//d是一个整型指针。
auto e=&cr;//e是一个指向整数常量的指针,对常量取地址是一种底层const
如果希望auto出的是顶层const就要明确指出。
const auto f = ci;//f是const int
也可以为引用设置auto
auto &g = ci;//g是一个整型常量引用。
auto &h = 42;//错,不可以为非常量引用绑定字母值。
const auto & j = 42; /正确,可以为常量引用绑定字面值。
设置一个类型为auto的引用时,初始值中的顶层const会保留。如果我们给初始值绑定一个引用,则常量就不是顶层常量了?
对于一条语句定义多个变量,切记,*和&只从属于某个声明符。
decltype ,选择并返回操数的类型。只分析其类型,不计算。
特别注意引用从来都作为其所引用对象的同义词出现,但decltype是个例外。
decltype((i))双层括号,的结果永远是引用,而decltype(i)的结果只有当i本身是引用时才是引用。
预处理变量无视c++语言总关于作用域的规则。
C11学习笔记 5
参数传递时,如果是引用类型,它将绑定到对应的实参上,否者,将实参的值拷贝后赋给形参。引用可避免拷贝,如果不需要改变参数,最好定义成常量引用。和其他初始化一样,当用实参初始化时会忽略顶层const,当形参有顶层const时,传给它常量对象或非常量对象都可以。我们可以用非常量初始化一个底层const对象...
C 11学习笔记 11
动态分配的内存,只有在显式释放是,这些对象才会销毁。但是标准库中的两智能指针可以确保自动释放。除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称作自由空间或堆。静态内存用来保存局部static对象 类static数据成员以及定义在任何函数之外的变量。栈内存用来保存定义在函数没得非stat...
C 11学习笔记 16
tuple是类型pair的模板。不同tuple类型的成员类型也不同,但一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的。当我们希望将一些数据组合成单一对象,但有不想麻烦地定义一个新数据结构来表示时,tuple是非常有用的。快速而随意 的数据结构 tuple类型及其伴随类...