“const”是指只读还是其他什么?
const
是什么意思? 只读似乎封装了我的意思,但是,我不确定我是对的。
如果只读和const
是不同的,有人可以告诉我为什么?
是什么促使这个问题是这个答案 ,他说, const
“只”意味着在C中只读。我认为这都是 const
意思,无论是C还是C ++。 他什么意思?
为了回答在C和C ++中const
的具体差异,我创build了一个新的问题: 在C和C ++中,“const”是如何不同的? 根据R ..的build议。
通过声明一个variables为const
你可以指示编译器,你没有修改该variables的意图。 但这并不意味着别人没有! 这只是为了让一些优化,并通过编译错误通知(注意,这主要是编译错误,而const == ReadOnly
将意味着运行时错误)。
const
并不意味着只读 ,因为你可以写const volatile
,这意味着它可以随时更改,但我无意修改它。
编辑:这里是一个经典的例子:考虑我写的代码,从内存映射端口读取当前时间。 考虑到RTC被映射到内存DWORD 0x1234。
const volatile DWORD* now = *(DWORD*)0x1234;
这是const
因为它是一个只读端口,它是volatile
因为每次我读它都会改变。
还要注意许多体系结构有效地使全局variables声明为const
只读,因为它是UB来修改它们的。 在这些情况下,UB将performance为运行时错误。 在其他情况下,这将是一个真正的UB 🙂
这是一个很好的阅读: http : //publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
编译器不允许声明为const
东西被修改。 这是你说的。
它主要用于函数原型来通知用户函数在传递指针时不会触及这个或那个。 它也可以作为你自己的失败保险。
很多人告诉你, const
意味着你不能修改它。 这显然是错误的 。 const
可以被抛弃。 注意这个片段:
void foo(const int *somevalue) { int *p = (int*) somevalue; *p = 256; // OMG I AM EVIL!!!!11 }
你的编译器不会阻止你这样做。 那么const
的目的是什么呢? 我会把它称为更多的build议。 它提醒你,当你看看你的function期望的合同的函数原型。 如果你不小心破坏它,你的编译器会对你大喊。 (但是,如果你故意破坏它,就像上面的演员一样。)
在某些情况下,标准有意打破const
。 注意strstr
的返回值,例如:根据定义,它会返回一些偏移量到你提供的const
缓冲区中…但是返回的值不是const
。 为什么? 那么,这将使用非常量缓冲区上的strstr
的返回值有意义的中断。
两个字节的字节相同(注释除外)最小案例示例…
首先在C中,gcc会发出一个警告。
/ *函数将指针指向一个数组 两个只读的整数* / void a(const int(* parray)[2]); void b(void) { int array [2] = {1,2}; const int crray [2] = {1,2}; / * C保留将其隐藏在只读位置的权利* / 一个(&数组); / *警告:从不兼容的指针types中传递“a”的参数1 * / (&crray); /* 好!*/ }
现在在C ++中也是这样… g ++对此非常满意。
//函数将一个指针指向一个数组 //它承诺不会修改的两个整数。 //(除非我们抛弃它的常量; -P) void a(const int(* parray)[2]); void b(void) { int array [2] = {1,2}; const int crray [2] = {1,2}; 一个(&数组); // C ++没有这个问题。 (&crray); // 好! }
C ++允许const成员函数的定义。 const成员函数是在const对象上调用的唯一函数。 此外,const成员函数不能修改任何类的数据成员(除非数据成员标记为mutable)。
class Foo { int data; void Bar(); void ConstBar() const; }; void Foo::ConstBar() const { // Error! cannot modify i as ConstBar is a const member function. // i = 0; } // Usage: const Foo foo_instance; // Error! cannot call non-const member on a const object. // foo_instance.Bar(); // OK foo_instance.ConstBar();
Const意味着一个指针或引用不能用于写或读 – 修改 – 写操作,而不会抛出const。 这并不意味着C ++标准试图声明它的意思(C ++标准只是错误的)。
一个像这样定义的variables:
/* auto */ int const x = 1;
显然不是只读的,否则无法初始化。 相反,variablesx的types是“引用const到int”(而不是对const int的引用),或者是int的lvalue const。 请注意,“const”与指针或引用关联,它与存储无关,也不存储在该存储中的值的types。
这是非常不幸的,因为const提供的契约是非常弱的,尤其是不能caching指向或指向的内存位置,这正是因为它并不意味着不可变的存储。
底线是:const是与符号引用或指针相关的访问修饰符 ,程序员使用该指针来允许符号提供者在符号客户端上build立义务,或者符号客户端承诺它不符号通过这个符号修改存储空间(例如,一个接受指针const的int函数保证不会修改int指针)。
这与variables无关:
int const *p = (int*)malloc(sizeof(int));
而且显然与存储无关(malloc'ed存储总是可写的)。
相反,你应该把const看作是在程序各部分之间传递不variables,义务或者需求的一种方式,由程序员为程序员的目的而设置,并且由types系统来传播。 不幸的是,types系统不健全,无法正确传播常量:
X *last; struct X { int a; X() : a(0) { last=this; } }; X const x; // x is const? last->a = 1; //really ??
恕我直言,编译器必须使存储不可变的唯一机会是实际的常量,如string文字(可能)或静态(全局)存储。 在实践中,自动,堆和临时存储不能是只读的。