我知道 const_cast
适用于指针和引用。
我假设const_cast
的输入应该是指针或引用。我想知道如果输入是指向const int
的指针/引用,为什么它不删除常量性?
以下代码按预期工作。
const_cast
(带有多级指针)
int main()
{
using std::cout;
#define endl '\n'
const int * ip = new int(123);
const int * ptr = ip;
*const_cast<int*>(ptr) = 321;
cout << "*ip: " << *ip << endl; // value of *ip is changed to 321
}
但是当我尝试指向const int
或指向const int
的指针时,该值似乎没有变化。
const_cast
,参考const int
int main()
{
using std::cout;
#define endl '\n'
const int i = 123;
const int & ri = i;
const_cast<int&>(ri) = 321;
cout << "i: " << i << endl; // value in 'i' is 123
}
const_cast
(带有指向const int的指针)
int main()
{
using std::cout;
#define endl '\n'
const int i = 123;
const int * ri = &i;
*const_cast<int*>(ri) = 321;
cout << "i: " << i << endl; // value in 'i' is 123
}
(1)可以正常工作,但是我无法理解为什么(2)和(3)不起作用我认为const_cast
的输入是指针/引用。
请帮助我了解其背后的哲学。谢谢。
答案 0 :(得分:18)
有两种常数。
对象的恒定性是对象的固有属性。无法更改。想想一本印刷书籍中的一页。可以将其视为字符串,并且无法更改。它说出了它的意思,就是这样。因此它是const string
。
现在想想一块黑板。它可能上面写着一些东西。您可以擦除它并写其他东西。因此黑板是一个非常量string
。
另一种常量性是指针和引用常量。此常数不是指向对象的固有属性,而是 permission 。它表示不允许您通过该指针修改对象 。它没有说明对象本身是否可以修改。
因此,如果您有const指针,则不一定知道它真正指向的是什么。也许是书页。也许是黑板。指针不告诉您。
现在,如果您确实知道它确实是一块黑板,那么您可能会很讨厌并要求获得许可才能继续操作并更改上面写的内容。这就是const_cast所做的。它允许您做某事。
如果您需要修改字符串的权限,而结果却是打印页面,该怎么办?您得到了您的许可,然后继续擦除它……然后……确切发生的是 undefined 。也许什么都没有。也许打印件被弄脏了,您既无法识别原始字符串,也无法在其上写下任何内容。也许您的世界爆炸成碎片。您可以尝试看看,但不能保证明天会发生同样的事情。
答案 1 :(得分:14)
(2)和(3)具有相同的原理,所以我只讨论(2)。
行
const_cast<int&>(ri) = 321;
具有未定义的行为。
您无法根据标准修改const
对象,即使使用const_cast
也是如此。如果您从指针/引用中删除const
,并且修改了指向/引用的对象,则必须首先不要将指向/引用的对象声明为const
。
const_cast
仅应在由于某种原因而拥有指向某物的const指针并且知道某物未声明为const
时使用。
答案 2 :(得分:3)
通过u_even = ycbcr[1::6]
u_odd = ycbcr[4::6]
u = (u_even + u_odd) / 2
yuyv[1::4] = u
修改常量是不确定的行为。
编译器发现您正在尝试打印一个常量,知道它永远不会改变,因此进行编译:
const_cast
收件人:
cout << "i: " << i << endl;
请参阅:https://godbolt.org/z/bYb0mx。启用优化后,它会将您的代码优化为仅打印123:https://godbolt.org/z/4Ttlmj。
最终,编译器会进行假设以创建更快/更小的代码,如果您进入未定义行为的领域,则其中一些假设可能是不正确的,并且会产生令人惊讶的结果。