对于之前我们学过的一些东西,时间久了很多东西就会忘记,这里我总结了一些知识点帮助大家回顾复习,今天第一讲我们来讲const,关于const的使用,你还记得多少?
const含义及作用
const大家一定不陌生,在学C语言的时候就认识过了const。const最基本的作用就是定义常量,这里再逐条进行梳理,帮助大家回忆。
const对象默认为文件局部变量
注意:非const变量默认为extern,要使const变量能在其他文件中访问,必须在文件中显式地指定它为extern。
未被const修饰的变量在不同文件的访问:
//file1
int num; //定义一个非const变量
//file2
#include <iostream>
extern int num;
int main()
{
std::cout << (num + 10) << endl;
return 0;
}
const常量在不同文件中的访问
//file1
//extern_file1.cpp
extern const int ext = 2;
//如果没有extren
//const int ext = 2; //会导致报错
//file2
#include <iostream>
extern const int ext;
int main()
{
std::cout << ext << std::endl;
return 0;
}
未被const修饰的变量不需要extern显式声明,但是const修饰的常变量如果想要跨文件访问,就必须要显式声明extern,而且需要做初始化,应为它一旦被创建便不可以被修改。
定义常量
还是之前所说过的,const修饰的变量为常变量,定义的时候必须初始化,定义后的变量不可以被修改!
const int b = 10;
const string s = "hello,world";
//const int a,b = 0;//这样写是错误的,a没有被初始化
指针与const
指向常量的指针
const修饰指针,老问题了,区别就在于const在“ * ”之前还是在“ * ” 之后,如果在“ * ”之前,那么限制修改的就是指针所指向的区域的内容了,反正限制的就是指针所指向的区域。如果之前有之后也有,那这个指针什么都修改不了。
还有一个注意的要点:允许把非const对象的地址赋值给指向const对象的指针。这叫权限的缩小,权限的缩小是可以的,但是权限不可以放大。
const int* ptr;
int val = 3;
ptr = &val;
上面代码中是不可以通过ptr来修改val的值的,即使它指向的是val的地址。
- 对于指向常量的指针,不能通过指针来修改对象的值。
- 不能使用void*类型指针保存const对象的地址,要使用const void*类型的指针保存const对象的地址
- 允许把非const对象的地址赋值给const对象的指针,这是一种权限缩小的操作
常指针
与指向常量的指针不同,常指针必须进行初始化,且const指针的值不能修改
//常指针
int num = 0;
int* const ptr2 = #
int* t = #
*t = 1;
cout << *ptr2 << endl;
修改ptr2指向的值,可以通过非const指针来修改。
常指针和指向常量的指针有什么区别?
常指针是在定义时必须先初始化的,因为常指针所指向的区域是不能被修改的,但是指向常量的指针在const修饰之后,不需要定义时初始化, 你可以任意改变指针所指向的区域。如果想要保证不报错,就要确保变量和指针之间权限的一致或权限缩小。
函数中使用const
const修饰函数返回值
const修饰函数返回值和修饰普通变量以及指针的含义基本相同。
这个很好理解,因为函数的返回值本身就赋值给别的变量以实现链式访问。如果返回值是指针,呢么这里要提一下:
const int* fun1();
//指针指向的内容不变
int* const fun2();
//指针本事不变
const修饰函数参数
const修饰函数参数本身就是限制参数被修改,但是我们知道函数的参数是一个临时参数,是形参的拷贝,所以在使用const限制的时候,一般会限制指针或引用类型的数据,防止数据被修改。
void StringCopy(char* dst,const char* src);
这个函数中,src是一个输入参数,而dst是一个输出参数,为了防止src参数被修改,就在src前面加const,如果函数中试图修改src所指向的内容,就会指出错误,这就是加了const的作用。
在学习了C++引入引用这个概念之后,我们知道了传参传引用可以避免拷贝,是一个提高效率的方法,但是会衍生出一些问题,就是引用传递有可能会改变实参的值,这是我们不希望看到的。const的修饰完美解决了这个问题。
void function(const C& c)
那么以此类推,在使用C++的时候是否应该将所有的参数写成const修饰的引用传参,以便提高效率?实际上是没有必要的,上面的代码的引用对象也是一个C类构造的对象c,因为如果是传参,就会有拷贝构造和函数结束后的析构的消耗,而内置类型的参数不存在这些消耗,值传递和引用传递的效率相当。
类中使用const
学习了C++之后,我们认识了类,在一个类中,任何不会修改成员变量的函数都应该被声明为const类型,const类型的成员函数本质上是用const修饰了this指针。
和之前的const指针一样,权限只可以被缩小不可以被放大,如果你创建了一个const对象,那么这个对象的成员变量是被const修饰的,那么这个对象还能正常访问所有的函数吗?
答案是不能的,const对象只能访问const成员函数,而非const对象可以访问所有的成员函数,包括const成员函数。
//file1
class test
{
private:
int _num;
public:
test(int i = 0)
:_num(i)
{}
void take() const;
void Add(int num);
};
//file2
#include <iostream>
#include "test.cpp"
using namespace std;
void test::take() const
{
cout << _num << endl;
}
void test::Add(int num)
{
_num += num;
}
int main()
{
test t1;
test const t2;
//t1.take(1); 会报错
t1.Add(2);
t2.take();
}
另外在这里提一下,static成员需要在类外定义,在类内只能进行声明,这是因为无论是static修饰的函数或是变量,本质都是属于类而不是类对象。所以要在类外定义。
今天的总结就到这里了,希望大家学习愉快!