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

发布于 2024-10-08 13:25:48 字数 453 浏览 3 评论 0原文

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

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

引发这个问题的原因是这个答案,其中他指出const“just”意味着只读C. 我认为这就是全部 const 的意思,无论它是 C 还是 C++。他是什么意思?

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

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

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

泪冰清 2024-10-15 13:25:48

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

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

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

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

它是const,因为它是一个只读端口,它是易失性,因为每次我读取它时,它都会改变。

另请注意,许多架构实际上将声明为 const 的全局变量设为只读,因为需要 UB 来修改它们。在这些情况下,UB 将表现为运行时错误。在其他情况下,这将是一个真正的 UB :)

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

By declaring a variable as const you 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 == ReadOnly would mean runtime errors).

const does 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.

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.

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

It's const because it's a read-only port, and it's volatile because each time I will read it it will change.

Also note that many architectures effectively make global variables declared as const read-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 :)

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

若无相欠,怎会相见 2024-10-15 13:25:48

编译器不允许修改声明为 const 的内容。正如你所说。

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

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

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.

单身情人 2024-10-15 13:25:48

很多人告诉您 const 意味着您无法修改它。这是明显错误的const 可以轻易地被丢弃。请注意这段代码:

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

您的编译器不会阻止您执行此操作。那么,const 的目的是什么呢?我更愿意称之为建议。当您查看函数期望的合约函数原型时,它会提醒您。如果你不小心破坏了它,你的编译器会对你大喊大叫。 (但如果你故意破坏它,就像上面的强制转换一样。)

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

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

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.)

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

殤城〤 2024-10-15 13:25:48

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

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

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

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

/* 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.

// 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!
}
欢烬 2024-10-15 13:25:48
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 [] 被视为可读,因为如果使用它,它就会被压入堆栈。

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.

如果没结果 2024-10-15 13:25:48

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

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).

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();
三岁铭 2024-10-15 13:25:48

Const 意味着指针或引用不能用于写入或读-修改-写操作,除非放弃 const。它并不意味着 C++ 标准试图声称的意思(C++ 标准在这一点上是错误的)。

像这样定义的变量:

 /* auto */ int const x = 1;

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

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

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

这与变量无关:

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

并且显然与存储关系不大(malloc 存储总是可写的)。

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

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

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

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).

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.

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.

The bottom line is: const is an access modifier associated 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).

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).

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:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文