“const”只是意味着只读还是更多?

时间:2010-12-20 01:52:04

标签: c++ c const

const到底意味着什么?只读似乎包含了它对我的意义,但是,我不确定我是对的。

如果只读且const不同,有人可以告诉我原因吗?

提示此问题的原因是this answer他在哪里说const“只是”意味着在C中只读。我认为所有 const意味着,无论如何无论是C还是C ++。他是什么意思?

为了回答C与C ++中const的具体差异,我根据R的建议创建了一个新问题:How does "const" differ in C and C++?

7 个答案:

答案 0 :(得分:46)

通过将变量声明为const,您可以指示编译器您无意修改该变量。但这并不代表别人没有!它只是允许一些优化并通过编译错误通知(注意,它主要是编译错误,而const == ReadOnly意味着运行时错误。)

const并不意味着只读,因为你可以写const volatile,这意味着它可以随时改变,但我无意修改它。

编辑:这是一个经典的例子:考虑我正在编写从内存映射端口读取当前时间的代码。考虑RTC映射到内存DWORD 0x1234。

const volatile DWORD* now = (DWORD*)0x1234;

它是const,因为它是一个只读端口,它是volatile因为每次我读它都会改变它。

另请注意,许多体系结构有效地将全局变量声明为const只读,因为它是修改它们的UB。在这些情况下,UB将表现为运行时错误。在其他情况下,它将是一个真正的UB:)

这是一个很好的阅读:http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

答案 1 :(得分:7)

编译器不允许修改声明为const的内容。就像你说的那样。

它主要用于函数原型,以通知用户函数在传递指针时不会触及此函数。它也适用于你自己的故障保护。

答案 2 :(得分:2)

很多人告诉你const意味着你无法修改它。那是显然是假的const可以轻易地被抛弃。请注意以下代码段:

void foo(const int *somevalue)
{
   int *p = (int*) somevalue;
   *p = 256;  // OMG I AM EVIL!!!!11
}

您的编译器不会阻止您这样做。那么,const的目的是什么呢?我更多地称之为建议。当您查看函数期望的函数原型时,它会提醒您。如果你不小心打破它,你的编译器会对你大喊大叫。 (但如果你故意打破它,就像上面演员一样。)

在某些情况下,标准会故意中断const。请注意strstr的返回值,例如:根据定义,它将向您提供的const缓冲区返回一些偏移量...但返回的值不是const。为什么?好吧,这会在非strstr缓冲区上使用const的返回值进行有意义的破解。

答案 3 :(得分:1)

字节相同的两个字节(注释除外)最小的例子......

首先在C中,gcc会发出警告......

/* Function taking a pointer to an array of
 two read only integers.*/
void a( const int (* parray)[2]);

void b(void)
{
   int array[2] = {1,2};
   const int crray[2] = {1,2}; 
/* C reserves the right to stash this in a read-only location.*/

   a( &array); 
/* warning: passing argument 1 of ‘a’ from incompatible pointer type*/
   a( &crray); /* OK!*/
}

现在在C ++中也是如此...... g ++非常满意。

// Function taking a pointer to an array 
// of two integers which it promises not to modify. 
// (Unless we cast away it's constness ;-P)
void a( const int (* parray)[2]);

void b(void)
{
   int array[2] = {1,2};
   const int crray[2] = {1,2};

   a( &array); // C++ has no problem with this.
   a( &crray); // OK!
}

答案 4 :(得分:0)

const char * hello_1{ "Hello!" };
const char   hello_2[]{ "Hello!" };
char       * ptr{};

// take away the const-nes
// ptr = (char *)hello_1;
// *ptr = '*'; <-- write access violation
// hello_1 is in a read only memory

// take away the const-nes
ptr = (char *)hello_2;
*ptr = '*'; // <-- OK
// hello_2 is modifiable

指针指向内存,char *指向数据段中的只读内存。 char *char []之间的区别在于,虽然两者在数据段上的声明方式相同,但char []被视为可读,因为如果使用它,它将被推送到堆栈中。 / p>

答案 5 :(得分:-2)

C ++允许定义const成员函数。 const成员函数是唯一在const对象上调用的函数。此外,const成员函数不能修改类的任何数据成员(除非数据成员标记为可变)。

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();

答案 6 :(得分:-4)

Const意味着指针或引用不能在不抛弃const的情况下用于写或读 - 修改 - 写操作。它并不意味着C ++标准试图声称它意味着什么(C ++标准在这方面是错误的。)

这样定义的变量:

 /* auto */ int const x = 1;

显然不是只读的,否则无法初始化。相反,变量x的类型是“引用const到int”(并且不引用const int)或者lvalue const of int。请注意,“const”与指针或引用相关联,它与存储无关,也与存储中的值类型无关。

这是非常不幸的,因为const提供的契约非常弱,特别是无法允许缓存指向或引用的内存位置,正是因为它并不意味着不可变存储。

底线是:const是一个访问修饰符,与符号引用或指针相关联,程序员使用该符号引用或指针允许符号提供者在符号客户端上建立义务,或者符号客户端承诺符号提供程序它不会通过此符号修改存储(例如,接受指向const的函数的int承诺不会修改指向的int)。

这与变量无关:

int const *p = (int*)malloc(sizeof(int));

并且显然与存储无关(malloc'ed商店总是可写的)。

相反,您应该将const视为一种在程序的各个部分之间传递不变量,义务或要求的方式,由程序员为程序员目的而实现,并由类型系统传播。不幸的是,类型系统不健全,无法正确传播常量:

X *last;
struct X { int a; X() : a(0) { last=this; } };
X const x; // x is const?
last->a = 1; //really ??

恕我直言,编译器必须使存储不可变的唯一机会是实际常量,例如字符串文字(可能)或静态(全局)存储。在实践中,无法将自动,堆和临时存储设置为只读。