我看到它被用在以下方式:
const int x = 5;
我知道这意味着
x
是一个常量变量,可能存储在只读内存中。但是,这些是什么?
void myfunc( const char x );
并且
int myfunc( ) const;
?
const int x = 5;
x
是一个常量变量,可能存储在只读内存中。void myfunc( const char x );
并且
int myfunc( ) const;
?
void myfunc(const char x);
这意味着参数x
是一个char类型的变量,其值在函数内部无法更改。例如:
void myfunc(const char x)
{
char y = x; // OK
x = y; // failure - x is `const`
}
对于最后一个:
int myfunc() const;
除非在类声明内部,否则这是非法的- const
成员函数防止修改任何类成员-不能使用const
非成员函数。在这种情况下,定义将是这样的:
int myclass::myfunc() const
{
// do stuff that leaves members unchanged
}
如果您需要在 const
成员函数中修改特定的类成员,您可以将它们声明为 mutable
。一个例子是成员 lock_guard
,它使该类的 const
和非const
成员函数线程安全,但在其自身内部操作期间必须更改。
mutable
,仅因为您在成员函数上误解了const
的含义而导致代码无法编译。 - Steve Townsend第一个函数示例基本上没有意义。更有趣的一个示例是:
void myfunc( const char *x );
这告诉编译器*x
的内容不会被修改。也就是说,在myfunc()
中你不能执行如下操作:
strcpy(x, "foo");
第二个例子是关于 C++ 成员函数的,意味着调用该函数时对象的内容不会被改变。
所以给定:
class {
int x;
void myfunc() const;
}
someobj.myfunc()
不允许修改任何东西,比如:
x = 3;
void myfunc( const char x );
x
,也就是说这是非法的:void myfunc( const char x ) {
x = ...;
}
当:
int myfunc() const;
只有当myfunc()是类中的一个方法时才有意义;这基本上意味着该方法不能修改类实例(即在调用instance.myfunc()之前和之后,实例的状态将保持不变)。
const
在变量标识符前面,表示该变量可以被初始化,并且之后不能再修改。
const
在类方法名称之后,表示该方法将不会修改类的可观察状态。而 mutable
关键字允许修改内部数据。
const
在指针或引用变量前,表示该标识符不会用于修改引用的数据,尽管可以通过其他方式进行更改。
const int *pInt = &x;
常量也可以用来表示指针本身不能被修改:
int * const pInt = &x;
const
的不同用法。根据你放置const
的位置,你告诉编译器某些东西应该是不可变的,或者某些东西不能改变其他东西。'something'可能是一个变量、一个指针或一个函数/方法,你不希望它能够改变传递给函数或对象成员变量的值。const
限定符表示一个被定义为 const
的变量/指针不能被程序更改,并且它将通过显式初始化或硬件相关手段接收其值。
在参数声明中定义为 const
的指针,函数代码将不会修改其所指向的内容。基本上,您可以使用该指针,并且它几乎起到 "只读" 的作用。
例如:
void foo(const char *x)
{
while(*x)
{
if(*x==' ') cout << '-'; //printing - when a space is encountered
else cout << *x;
x++;
}
}
上述函数很好,不会显示任何错误。但是如果foo有任何可以更改传递的字符串的东西。比如一个将空格替换为$的函数。不是打印$而是将其更改为$。类似于这样:
void foo(const char *x)
{
while(*x)
{
if(*x==' ') *x = '$'; //printing - when a space is encountered
else cout << *x;
x++;
}
}
那么它就无法编译,即将一个值赋给只读内存位置的错误。
#include <iostream>
void break_const(const int x) {
const int* x_ptr = &x;
std::intptr_t z = reinterpret_cast<std::intptr_t>(x_ptr);
int* hacked = reinterpret_cast<int*>(z);
*hacked = 3;
std::cout << "x = " << x << std::endl;
}
int main() {
break_const(5);
return 0;
}
输出结果为 "x = 3."
编辑:我还应该补充一点,我的说法 "这意味着标识符不能直接更改" 有些不准确。对于整数来说,这是可以的。但对于更复杂的类型,const 的含义就更少了(例如类中的 mutable)。
两者之间的区别在于第一个具有类型void(char)
,而第二个具有类型int()const
。
具有带有const
结尾的此类类型的函数只能是类的成员函数,并且这意味着从类外部看,成员函数不会改变类值(指this
所指向的值)。编译器会对此进行一定程度的检查,任何直接对常量成员函数中类成员的写入都将导致编译时错误,并且该函数只能直接调用其自身的常量成员函数(存在特殊指令,可以告诉编译器成员写入不会从外部更改类的值。这通过使用mutable
关键字实现)。
在您提供的函数中,其中一个参数的类型为char const
。这种参数在其函数内部无法更改。它对函数类型或调用者没有影响。
void myfunc(const char x)
非常类似于你的例子中的 const int x = 5
:它声明了一个在函数 myfunc
内部可用的常量。由于它是一个常量,它的值不能被改变。
int myfunc() const
是一个类的成员函数。其中的 const
表示该函数不会改变执行函数的类实例。因此,在函数内部,你不能像这样做:this->foo = 7
或者调用其他非 const 的函数。