1.赋值与初始化
初始化不同于赋值,初始化是创建变量并临时赋予其一个初始值,而赋值是把对象当前值擦除,而以一个新值来替代。 -------《C++ Primer 第五版》 p39
定义在函数体内的内置类型对象如果没有初始化,则其值为定义。类的对象如果没有显式的初始化,则其值由类决定。 -------《C++ Primer 第五版》 p40
代码1.1 定义在函数体内的内置类型没有初始化
#include <iostream>
using namespace std;
void print(){
int num_int;
double num_double;
char num_char;
cout << "int :" << num_int << endl;
cout << "double: " << num_double << endl;
cout << "char: " << (int)num_char << endl;
}
int main(){
print();
return 0;
}
运行结果:
注意:此处的值并不是固定的,而是随机生成的。
代码1.2 定义在函数体内外的内置类型没有初始化
#include <iostream>
using namespace std;
int num_int;
double num_double;
char num_char;
void print(){
cout << "int :" << num_int << endl;
cout << "double: " << num_double << endl;
cout << "char: " << (int)num_char << endl;
}
int main(){
print();
return 0;
}
运行结果:
探讨:main函数内的值会初始化默认值吗?
测试后结果:main函数也属于函数,所以不会初始化,其值为定义。
2.声明与定义
声明不等同于定义,声明只是使得名字被程序所知,而定义还会申请存储空间,也可能会位为变量赋一个初始值。且变量能且只能被定义一次,但是可以被多次声明。 -------《C++ Primer 第五版》 p41
代码2.1 多次声明
#include <iostream>
#include "head.h"
using namespace std;
extern int ext;
extern int ext;
extern int ext;
extern int ext;
extern int ext;
int main(){
return 0;
}
3.作用域
c++允许在内层作用域定义外层作用域已有的名字。 -------《C++ Primer 第五版》 p44
代码3.1 内层作用域定义外层作用域已有的名字
#include <iostream>
using namespace std;
int result = 3;
int main(){
int result = 1;
cout << result << endl;
return 0;
}
运行结果:
可以看出内层作用域的值覆盖了外层作用域,也就是局部变量覆盖了全局变量。
代码3.1 使用“ :: ”取得全局变量的值
#include <iostream>
using namespace std;
int result = 3;
int main(){
int result = 1;
cout << "result : " << result << endl;
cout << "::result : " << ::result << endl;
return 0;
}
运行结果:
注:在for循环体上定义的变量属于for作用域,例如如下代码运行结果是10。
#include <iostream>
using namespace std;
int result = 3;
int main(){
int i = 10;
for(int i = 0; i < 100; i++){
//do something
}
cout << i;
return 0;
}
4.左值引用
引用必须被初始化。 -------《C++ Primer 第五版》 p45
引用在内存上如下图所示:
int lvalue = 10;
int lvalue_reference = &lvalue;
引用类型的初始值必须是对象。 -------《C++ Primer 第五版》 p46
下图写法就是错的:
引用本身并不是一个对象,一旦定义了引用,就无法解绑再去绑定另一个对象。 -------《C++ Primer 第五版》 p49
5.void* 指针
void*指针可以用于存放任意对象的地址。 -------《C++ Primer 第五版》 p50
#include <iostream>
using namespace std;
int main(){
int *p = nullptr;
void *ptr = p;
}
但是void*仅限于存放对象地址,不能通过void*访问到对像的内容,例如以下写法就是错的:
#include <iostream>
using namespace std;
int main(){
int i = 5;
int *p = &i;
void *ptr = p;
cout << *ptr << endl; //错误
}
可以通过static_case转换使得void*类型访问到对象,这里只做演示,不深究,代码如下:
#include <iostream>
using namespace std;
int main(){
int i = 5;
int *p = &i;
void *ptr = p;
cout << *static_cast<int*>(ptr) << endl;
return 0;
}
运行结果:
6.const
const修饰的变量必须初始化
默认情况下const对象仅在文件内有效 -------《C++ Primer 第五版》 p54
对于上面的const对象仅在文件内有效,一开始测试错误,以为是书上写错了,后来用了正确的测试方法,验证了书上的说法。
错误测试:
head.h
#ifndef HEAD_H
#define HEAD_H
const int con = 10;
#endif
main.cpp
#include <iostream>
#include "head.h"
using namespace std;
int main(){
cout << con;
return 0;
}
运行结果:
结果惊人的发现在main文件中居然可以使用con,以为是书上写错了,或者是编译器问题,后来仔细思考发现,main.h中使用了#include "head.h" 这个语句其实以及将head文件包含进了main文件,如果将这句删除,那么程序就会报错。
代码6.1 删除include语句
#include <iostream>
using namespace std;
int main(){
cout << con;
return 0;
}
运行结果:
[Error] 'con' was not declared in this scope
这时候按着书上的使用extern修饰来测试。
正确测试:
head.h
#ifndef HEAD_H
#define HEAD_H
extern const int con;
#endif
head.cpp
#include "head.h"
extern const int con = 10;
main.cpp,不include头文件,只声明。
#include <iostream>
using namespace std;
extern const int con;
int main(){
cout << con;
return 0;
}
运行结果:
这个实验使得我对extern和const的作用又有了深入的理解。