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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4486326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:31:58  来源:igfitidea点击:

Does "const" just mean read-only or something more?

c++cconst

提问by Kim Sun-wu

What does constreally mean? Read-only seems to encapsulate its meaning for me, but, I'm not sure I'm right.

什么是const真正的意思?只读似乎概括了它对我的意义,但是,我不确定我是对的。

If read-only and constare different, could someone tell me why?

如果只读和const不同,有人能告诉我为什么吗?

What prompted this question was this answerwhere he states const"just" means read-only in C. I thought that's allconstmeant, regardless of whether it was C or C++. What does he mean?

促使这个问题的原因是这个答案,他说const“只是”在 C 中表示只读。我认为这就是全部const意思,无论是 C 还是 C++。他什么意思?

For an answer to the specific differences in constin C vs C++, I've created a new question: How does "const" differ in C and C++?as per R..'s suggestion.

为了回答constC 与 C++ 中的具体差异,我创建了一个新问题:C 和 C++ 中的“const”有何不同?根据R..的建议。

回答by ruslik

By declaring a variable as constyou indicate compiler that you have no intentions of modifying that variable. But it does not mean others don't have! It's just to allow some optimization and to be notified by a compile error (note, that it's mostly compile error, while const == ReadOnlywould mean runtime errors).

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

constdoes not mean read only, because you can write const volatile, that would mean it could change by itself anytime, but I have no intentions to modify it.

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

EDIT: here is a classical example: consider I'm writing the code that reads current time from a memory-mapped port. Consider that RTC is mapped to memory DWORD 0x1234.

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

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

It's constbecause it's a read-only port, and it's volatilebecause each time I will read it it will change.

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

Also note that many architectures effectively make global variables declared as constread-only because it's UB to modify them. In these cases UB will manifest itself as a runtime-error. In other cases it would be a real UB :)

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

Here is a good reading: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

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

回答by slezica

The compiler won't allow something declared as constto be modified. It is as you say.

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

It's mostly used in function prototypes to inform the user that a function won't touch this or that when passed pointers. It also works as kind of failsafe for yourself.

它主要用于函数原型中,以通知用户在传递指针时函数不会触及 this 或 that。它也可以作为自己的故障保护。

回答by asveikau

A lot of people are telling you that constmeans you can't modify it. That is patently false. constcan trivially be cast away. Note this snippet:

很多人告诉你,这const意味着你不能修改它。那显然是错误的const可以轻而易举地被抛弃。注意这个片段:

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

Your compiler will not stop you from doing this. So, what then is the purpose of const? I'd call it more of a suggestion. It reminds you as you look at function prototypes of the contract that your functions expect. Your compiler will yell at you if you carelessly break it. (But not if you intentionally break it, as with the above cast.)

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

In some cases the standard intentionally breaks const. Note the return values of strstrfor example: by definition it will return some offset into the constbuffer you provide it... But the returned value is not const. Why? Well, this would break meaningfully using the return value of strstron a non-constbuffer.

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

回答by John Carter

Two byte for byte identical (except for the comments) minimal case examples...

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

First in C, gcc will emit a warning...

首先在 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!*/
}

Now the same thing in C++... g++ is quite happy with it.

现在在 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!
}

回答by John Carter

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

Pointers point to memory, and char *points to memory in the data segment which is read only. The difference between char *and char []is that while both are declared the same way on the data segment, char []is treated as readable because it is pushed onto the stack if it is used.

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

回答by Sanjit Saluja

C++ allows for the definition of const member functions. const member functions are the only functions that be called on const objects. Also, const member functions cannot modify any data members of a class (unless the data member marked mutable).

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

回答by Yttrill

Const means that a pointer or reference cannot be used for a write or read-modify-write operation without casting away const. It does NOT mean what the C++ standard tries to claim it means (the C++ standard is just wrong on this).

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

A variable defined like this:

一个这样定义的变量:

 /* auto */ int const x = 1;

is patently NOT read-only since otherwise it could not be initialised. Rather, the kind of variable x is "reference const to int" (and NOT reference to const int) or alternatively lvalue const of int. Note carefully the "const" is associated with a pointer or reference it has nothing to do with the storage, nor the type of the value residing in that storage.

显然不是只读的,否则无法初始化。相反,变量 x 的类型是“对 int 的引用 const”(而不是对 const int 的引用)或 int 的左值 const。请注意,“const”与指针或引用相关联,它与存储无关,也与驻留在该存储中的值的类型无关。

This is rather unfortunate because the contract provided by const is extremely weak, and in particular fails to allow caching of a pointed at or referred to memory location, precisely because it does NOT mean immutable storage.

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

The bottom line is: const is an access modifierassociated with a symbolic reference or pointer which is used by the programmer to allow the symbol provider to establish an obligation on the symbol client, or for the symbol client to promise the symbol provider it does not modify storage via this symbol (for example a function accepting a pointer const to int promises not to modify the pointed at int).

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

This has nothing to do with variables:

这与变量无关:

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

and clearly little to do with storage (malloc'ed store is always writable).

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

Instead you should think of const as a way of communicating invariants, obligations or requirements between parts of the program, put in place by the programmer for the programmers purposes, and propagated by the type system. Unfortunately the type system isn't sound and fails to properly propagate constness correctly:

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

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

IMHO the only opportunity a compiler has to make store immutable is for actual constants such as string literals (maybe) or static (global) storage. Automatic, heap, and temporary storage cannot be made read-only in practice.

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