目录
------如有不对的地方, 请指正,感谢!
1、const修饰普通变量
int main()
{
const int a = 0;
a = 1; //错误,a被const修饰,编译器就会认为a是常量,不可以修改
int b = a; //正确,a可以用来给其他的变量赋值
return 0;
}
int main()
{
const int a = 10;
int* p = (int*)&a;
*p = 20;
cout << a << " " << *p << endl; //输出的结果是10, 20
return 0;
}C++中被const修饰的变量会被认为是常量,还具有替换的作用,编译器在编译的时候在程序中看到对应的变量会直接用常量中的内容替换。
*p刚开始也是10,然后直接找到a对应的地址之后将其中的内容修改成了20,所以*p打印的就是20。
2、const修饰指针变量
int main()
{
int a = 10;
int const* p = &a; //const 修饰指针指向的内容----指针指向的内容不可被修改
*p = 20;
const int *p1 = &a; //const 修饰指针指向的内容----指针指向的内容不可被修改
*p1 = 20; //错误
int* const p2 = &a; //const const修饰指针----指针的不可被修改
p2 = nullptr; //错误
const int* const p3= &a; //const即修饰指针指向的内容又修饰指针----指针指向的内容和指针都不可被修改
*p3 = 20; //错误
p3 = nullptr; //错误
return 0;
}
3、const修饰函数参数
3.1值传递
一般值传递不需要用const修饰,因为在调用函数的时候先将原函数的值拷贝一份过去给被调用的函数,在被调用函数中对该值的修改不会对原函数中的值有任何影响。
但是对于自定义类型,传参的时候尽可能的使用传引用来代替传值。因为对象一般都含有较多的数据成员,当其作为函数参数传递时,得拷贝一份,这就得调用拷贝构造函数,完事了还得调用析构函数,所消耗的资源比较大。所以一般采用const + 引用的方式(引用传递不需要产生临时对象),这样消耗小了,也不用担心所引用的值被修改。
class A
{
public:
A(int a = 1)
:_a(a)
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
void Print()const
{
cout << _a << endl;
}
private:
int _a;
};
void Demo(const A& a)
{
a.Print();
}
int main()
{
A a(10);
Demo(a);
return 0;
}
3.2址传递
址传递也可以说是值传递,因为传递过去的是一个地址,而被调用的函数可以通过该地址对其所指向的内容完成修改。
void Modify(int* p)
{
*p = 20;
}
int main()
{
int a = 10;
Modify(&a);
cout << a << endl;
return 0;
}
如果即想用址传递又不想所指向的内容被修改,可以用const修饰一下
void Modify(const int* p)
{
*p = 20; //错误,const修饰了*p 所以p指向的内容不可以被修改
}当然如果你想修改也不是不可以,你可以在里面创建一个变量,将p赋值给它就ok,int* p1 = p, *p1 = 20;这样就是欧克的。
4、const修饰函数返回值
4.1、const修饰的返回值为普通值
没有意义,因为函数在返回值的时候会将需要返回的值先拷贝一份到临时存储单元中。
4.2、const修饰的返回值为指针
如果const修饰的函数的返回值是指针,那么返回值指向的内容不允许被修改。并且返回值只能够赋值给const修饰的同类型的指针
const char* Fun()
{
nullptr;
}
int main()
{
char* p = Fun(); //错误
const char* p = Fun(); //正确
const int a = 10;
int b = a;
int c = 10;
return 0;
}
4. 3、const修饰的返回值为引用
返回的时候一定要注意的是这个引用一定不是临时对象的引用,不然会出现错误。一般会是类的成员变量或者是函数参数。
int& Demo()
{
int x = 0;
return x; //这是错误的,x会在函数调用后就会被释放
}int main()
{
int a = Demo();
return 0;
}
而正确的加const修饰的引用返回目的在于让函数调用的表达式不能作为左值使用。例如有下面这个函数:
int& Demo(int& x)
{
return x;
}
可以对函数的返回值进行赋值:Demo(x) = 10;
但是在前面加上了const之后就不能给它的返回值赋值了:const int& Demo(int& x)
一般返回引用会出现在类的赋值函数中,这样就可以连续赋值。
class A
{
public:
A& operator=(const A& a){}
};int main()
{
A a, b, c;
a = b = c; //欧克的(a = b) =c; //欧克的
return 0;
}
但是在函数A& operator=(const A& a){} 前面加上const之后:
a = b = c; //欧克的
(a = b) =c; //错误的,因为先计算出来的(a = b)返回的是一个const修饰的对象,作为左值不可以被赋值了。
5、const修饰非静态成员函数
非静态成员函数参数里面都会默认带有this指针,指向该对象的内存地址。const的作用就是修饰this指针,防止其修改成员属性。
class A
{
public:
int Demo()const
{
_a += 1; //错误,_a不可以被修改
Demo2(); //错误,一个成员函数被标记为const,则它不能调用一个非const的成员函数,也就是说不能改变对象的内部数据.
}int Demo2()
{
_a += 1;
return _a;
}
private:
int _a;
};想要修改的话可以:mutable int _a; 这样就可以修改了