【发布时间】:2010-09-18 04:59:29
【问题描述】:
我经常使用指向 const 对象的指针,像这样......
const int *p;
这仅仅意味着您不能通过p 更改p 指向的整数。但我也看到了对 const 指针的引用,声明如下......
int* const p;
据我了解,这意味着指针变量本身 是常量——您可以更改它整天指向的整数,但不能让它指向其他东西。
那有什么可能的用途?
【问题讨论】:
我经常使用指向 const 对象的指针,像这样......
const int *p;
这仅仅意味着您不能通过p 更改p 指向的整数。但我也看到了对 const 指针的引用,声明如下......
int* const p;
据我了解,这意味着指针变量本身 是常量——您可以更改它整天指向的整数,但不能让它指向其他东西。
那有什么可能的用途?
【问题讨论】:
当您为嵌入式系统设计 C 程序或需要引用同一内存的特殊用途程序(共享内存的多处理器应用程序)时,您需要常量指针。
例如,我有一个32 bit MIPs processor,它附加了一个little LCD。我必须将 LCD 数据写入内存中的特定端口,然后将其发送到 LCD 控制器。
我可以#define 该数字,但我还必须将其转换为指针,而当我这样做时,C 编译器没有那么多选项。
此外,我可能需要它是易失性的,也可以强制转换,但使用提供的语法更容易和更清晰 - 一个指向易失性内存位置的 const 指针。
对于 PC 程序,一个例子是:如果你设计 DOS VGA 游戏(网上有教程很有趣,可以学习基本的底层图形),那么你需要写入 VGA 内存,可以参考作为 const 指针的偏移量。
-亚当
【讨论】:
barrier() 和其他语义。确实,您需要仔细处理这些值。即缓存/无缓存、屏障等。这取决于设备的类型,volatile 并不总是最佳选择。
volatile 肯定应该在那里;另一方面,许多编译器供应商的头文件似乎并不在意——这可能有点烦人(因为即使编译器通常做正确的事情,他们也可能会忽略读取寄存器的尝试,但对结果)。
它允许您保护指针不被更改。这意味着您可以保护基于指针永不更改或无意修改的假设,例如:
int* const p = &i;
...
p++; /* Compiler error, oops you meant */
(*p)++; /* Increment the number */
【讨论】:
const uint8 *const value 之类的东西。这声明了指针和它指向的值是不可修改的(但可以被强制转换)。
另一个例子: 如果您知道它的初始化位置,则可以避免将来的 NULL 检查。 编译器保证指针永远不会改变(为 NULL)……
【讨论】:
在任何非 const C++ 成员函数中,this 指针的类型为 C * const,其中 C 是类类型——您可以更改它指向的内容(即它的成员),但您可以不要将其更改为指向C 的不同实例。对于const 成员函数,this 的类型为const C * const。还有(很少遇到)volatile 和 const volatile 成员函数,this 也有 volatile 限定符。
【讨论】:
一种用途是在低级(设备驱动程序或嵌入式)代码中,您需要引用映射到输入/输出设备(如硬件引脚)的特定地址。某些语言允许您链接特定地址的变量(例如,Ada 有use at)。在 C 中,最惯用的方法是声明一个常量指针。请注意,此类用法还应具有volatile 限定符。
其他时候只是防御性编码。如果您有一个不应该更改的指针,明智的做法是声明它不能更改。这将允许编译器(和 lint 工具)检测修改它的错误尝试。
【讨论】:
当我想避免对指针的意外修改(例如指针算术,或在函数内部)时,我总是使用它们。您也可以将它们用于单例模式。
'this' 是一个硬编码的常量指针。
【讨论】:
与“const int”相同......如果编译器知道它不会改变,它可以是基于此的优化假设。
struct MyClass
{
char* const ptr;
MyClass(char* str) :ptr(str) {}
void SomeFunc(MyOtherClass moc)
{
for(int i=0; i < 100; ++i)
{
printf("%c", ptr[i]);
moc.SomeOtherFunc(this);
}
}
}
现在,编译器可以做很多事情来优化那个循环——只要它知道 SomeOtherFunc() 不会改变 ptr 的值。使用 const,编译器知道这一点,并且可以做出假设。没有它,编译器必须假设 SomeOtherFunc 会改变 ptr。
【讨论】:
const 对优化有何影响?任何聪明的编译器都可以判断你是否修改了一个变量,如果可以根据它进行优化,不管你说你会不会。
ptr 是公共成员。编译器很难跨模块跟踪公共变量的使用。许多人甚至不会尝试,只会将其视为volatile 2) 9 年前编译器更笨。
我见过一些 OLE 代码,其中有一个从代码外部传入的对象,要使用它,你必须访问它传入的特定内存。所以我们使用 const 指针来确保函数始终操作的值比通过 OLE 接口传入的值。
【讨论】:
已经给出了几个很好的理由作为这个问题的答案(内存映射设备和只是简单的旧防御性编码),但我敢打赌,在大多数情况下,你看到这实际上是一个错误并且意图是必须 item 是一个指向 const 的指针。
我当然没有数据支持这种预感,但我还是会打赌。
【讨论】:
const 对优化有什么影响?任何聪明的编译器都可以判断你是否修改了一个变量,如果可以根据它进行优化,不管你说你会不会。
将 type* 和 const type* 视为类型本身。然后,您就会明白为什么您可能想要拥有这些类型的 const。
【讨论】:
始终将指针视为 int。这意味着
object* var;
其实可以认为是
int var;
所以,一个 const 指针仅仅意味着:
const object* var;
变成
const int var;
因此你也不能改变指针指向的地址,仅此而已。为防止数据更改,您必须将其设为指向 const 对象的指针。
【讨论】:
ints,在很多方面。此外,这个问题非常明确地表述为关于const 指针,而不是指向const 对象的指针。但无论如何,你把它们弄错了。