一个常量是保护通过指针传递给函数的变量是什么意思?
例如 :
int f ( const int vec[]);
以下命令不合法:
vec[i] = exp;
const
保护它的左侧,除非它的左边没有任何东西,然后它只保护它的右侧。在这种情况下,它保护vec
中包含的值。
这些例子可以帮助您理解这一点:
指向const变量的指针:
int vec[] = {1,2,3};
int const *ptr = vec;
ptr[1] = SOMETHING; //ERROR :(
一个指向变量的const指针:
int vec[] = {1,2,3};
int* const ptr = vec;
ptr[1] = SOMETHING; //OK :)
ptr = NULL; //ERROR :(
这些图片可以帮助您更好地理解这一点:
const是由编译器强制执行的限定符。什么
const int vec[];
意思是你不能修改vec中包含的int。
注意:这并不意味着内存不可修改。人们倾向于将const误认为运行时保证来保护那部分内存......事实并非如此。这只是c编译器强制执行的操作,试图保护程序员不要做愚蠢的事情。
编辑:const最明显的用途,因为它与函数调用有关,就是当你想通过引用传递东西时,因为它们很大并且复制它们会很昂贵。但是你想保证函数不会修改它们。
int someFunction(const int ¬Changeable, int &modifiable);
在上面的声明中,someFunction可以更改可修改的整数,并且由于它是通过引用传递的,因此对于调用例程也会更改。不应修改notChangeable int。
下面是一些使用const和指针可以做的令人讨厌的事情的例子。由于人们在谈论修改内存,并且只是编译时保证,我想我会演示这对你意味着什么。
#include <iostream>
#include <cstring>
using namespace std;
int main() {
const int* intOne = new int(10);
int* intTwo = new int(20);//Toggle these two lines
//int* const intTWo = new int(20);//Toggle these two lines
cout << *intOne << " " << *intTwo << endl;
intTwo -= sizeof(int); //Let's move our pointer back one integer!
*intTwo = 50000;//Now let's change that integer
cout << intOne << " " << intTwo << endl;//INteresting our pointers point to the same memory now
cout << *intOne << " " << *intTwo << endl;//And we were able to modify *intOne... even though it was const.
}
还要注意我们已经泄露了intTwo所指出的内容,虽然我们知道如何回到它,所以这并不可怕。如果你想看到使指针保持不变和它指向恒定的东西之间的区别,你可以切换我评论的两行。
预期产量:
10 20
0x1061009e0 0x1061009e0
50000 50000
该声明可以被理解为“一个int
的数组,它们是const”,或“一个整数数组,其值不能被改变”。这就是为什么该命令不合法:它会改变其中一个int的值。
当某个变量在参数列表中声明为const
时,该变量不能在函数体中修改。编译器将捕获任何尝试这样做的尝试。换句话说,声明为const
的变量不是合法左值。
它是一个修饰符,以确保您不直接修改变量值。它不会保护您不以其他方式修改内存,例如通过指针。当你知道自己不想改变某些东西时,使用它会很好,但是依赖它是不好的。
它使代码内部函数不会意外地修改传递对象的数据,因为编译器会给出错误。
数组通过其基址的引用传递。对于像int
变量这样的普通原语不是这种情况,如果传递一个整数,则在函数的作用域中创建局部变量并传递值,如果是chnages,则它们仅到局部变量。但是,由于阵列不是这种情况,你可能会意外地修改像array[i]=2
这样的东西。但是,如果使用const
限定符声明,则会被阻止。这就是关键字的本质。
这就是为什么许多人使用该原型,尤其是图书馆作家。因为,库被大量用户使用。函数中的一个错误,由于意外写入可以使用用户的堆栈...
当然,但这可能无法阻止故意攻击,因为它只编译时间,并且可以轻松地解决这个问题。
其他人已经说过,声明中显示的const *
参数告诉编译器指向的数据只读。我想给出更高层次的解释,说明为什么人们想要以这种方式声明函数的参数。该声明背后的想法是告诉读者您的应用程序,您的函数不会修改您传递的数据。
这是你的界面做出的承诺,告诉它不会有意想不到的副作用。
相反,缺少const声明表明缓冲区可能会被更改。
这也是为什么将const *
传递给期望只有一个简单*的函数会产生警告但反过来不会产生警告的原因。
示例:strlen
被声明为size_t strlen (const char *s)
,因为我可以推断出我可以调用它而不会有修改数据的危险。 strtok
被宣布为char *strtok (char *s, const char *delim)
,我认为我传递的缓冲区已被修改,必须小心。
TL; DR const添加有关函数属性的信息。