多年来,这已被弃用:
char *p = "abc";
然后在C ++ 11中变得非法。但是,许多人并不知道这是合法的:
char *p = (char*)"abc";
问题是:
[C ++ 11,diff.lex]有正当理由将字符串文字视为指向潜在可修改内存的指针的程序可能很少见。
有合理的理由吗?请关注托管环境。
答案 0 :(得分:3)
理由是,您可以拥有一个大型遗留代码库,其中char *
即使对于只能读取的参数也会被传递。强制转换为const char *
可能会导致巨大的代码更改,从而无法获得真正的好处(在某些情况下甚至会强制代码重复)。
请注意,转换为(char *)
a (const char *)
的能力不是一个特殊规则(你总是可以抛弃指针和引用的常量,如果没有实际的写操作,则代码是合法的指向/引用的对象被声明为常量。)
另请注意,const char *
并不意味着指向的char是常量(即无法写入),而只是不允许您使用该指针进行写操作< / strong> ...如果指向的对象不是常数并且还有其他方法可以达到它(例如锯齿),它实际上可以改变。
指针和引用的约束是指针/引用的属性,而不是引用对象的属性。可能“const指针”确实是一个坏名字,“只读指针”本来更合适。
答案 1 :(得分:1)
这不是特别特别。这也是合法的:
const int x = 3;
int *ptr = (int *) &x;
答案 2 :(得分:1)
传统代码(我们从VC ++ 6开始使用此功能进行了一些迁移),更一般地说,代码中有一些函数可能会根据其他条件修改其参数,或者具有不受限制的条件。签名有其他原因(通常,与C的兼容性,其中不能进行重载)。
答案 3 :(得分:1)
问题是仍然存在一些非常旧代码(或由不谨慎的程序员编写的旧代码片段),主要是C代码,其中一些例程可以使用指针char,从不修改指向数组,但仍然省略签名中的const
修饰符。
如果你想避免const_cast
删除常量,那么懒惰的workaroud就是直接将字符串litteral声明为char *
而不是const char *
,如果程序员确保它将会永远不会被修改。这只意味着由于编译器不再能够注意到对可能不可修改的字符串的修改尝试,程序员必须自己完成。
它甚至可能不会让K&amp; R C早期的旧程序员(const不存在)或汇编语言变得厌烦,但它很糟糕,因为它会混淆未来的维护者。
我的观点是,这在几年或几十年前是可以接受的,当时很多第三方代码都没有在签名中使用const
,并且不断重复const_cast
真的很无聊,但我现在这样做了同意引用:我无法想象当前写char * p = "abc";
的正当理由,而不是(vade retro satanas)char * p = (char *) "abc";
答案 4 :(得分:0)
作为旧代码可能利用可变字符串文字的示例,想象一下状态机中的无数位置替换工作队列la strtok("step-one|step-two|step-three|step-four", "|")
,其中strtok(NULL, "|")
从各种各样的队列中取代功能
请注意,如果同一个呼叫网站 - strtok("step-one|step-two|step-three|step-four", "|")
- 再次被执行,后续strtok(NULL, "|")
次呼叫将立即返回NULL
,因为该字面值的第一个strtok
调用会在第一个令牌之后将其分隔。
从任何替换strtok(str, delim)
函数获取相同的行为,没有可变/未加密的字符串文字 - 仅使用C ++标准功能 - 对我来说似乎很难。
如果这个确切的行为与应用程序所需的相匹配,并且应用程序是在可修改的文字未被弃用时首先编写的,那么开发人员可能会觉得他们“将字符串文字视为指针的正当理由可能可修改的内存“,因为它允许最简洁和简单的代码具有这种特殊的行为。