C++ primer学习笔记——p39-p54

本文概述了C++中的初始化、声明的区别,作用域规则,以及左值引用的特性。讨论了函数内变量初始化、const对象的作用域和void*指针的使用。重点介绍了如何理解变量声明与定义、引用的初始化规则以及void*的特殊用途。
摘要由CSDN通过智能技术生成

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的作用又有了深入的理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值