我们都知道应该避免使用const_cast来删除指针的常量。
但是如何相反呢?
对于我的用例,我有一个从非const源缓冲区复制数据(字节)的函数。 我认为一个好的设计决定是根据源缓冲区完全const来声明参数。
void copyfunction(const char* const data) { ... }
对于如下所示的函数调用,这将导致指针类型错误'const char * const< - >字符*”。
void main() {
char sourcebuffer[] = {0x00};
copyfunction(sourcebuffer);
}
当然,现在我可以简单地将sourcebuffer
声明为const,但在我的情况下,我无法访问该变量,因为它来自不同的代码位置(外部库)。
void main() {
char sourcebuffer[] = {0x00};
copyfunction(const_cast<const char* const>(sourcebuffer));
}
然而,超出的代码可以工作,但它是好的风格(根据我的用例)?
我认为声明copyfunction
的参数为const可以确保用户不修改(只读)指针或源缓冲区本身的位置。
所以在这种情况下,const_cast只是启用函数调用的必要之恶,而不是故意删除指针的常量......
迎接
答案 0 :(得分:5)
您不应使用const_cast
添加const
,因为:
没必要。 T*
隐式转换为const T*
。您的问题表明char sourcebuffer[] = {0x00}; copyfunction(sourcebuffer);
是一个错误,但事实并非如此。
它可能(虽然不太可能)有害。它可以从指针类型中删除volatile
,这不是此处的意图,如果sourcebuffer
被声明为volatile sourcebuffer[]
,则会导致未定义的行为。
答案 1 :(得分:5)
您不应使用const_cast
添加const
,因为
在操作安全的情况下,几乎总是不需要。 int*
隐式变为const int*
。
它可以做一些你不希望它做的事情。它可以剥离volatile
,或者让你错过const
已添加到变量中的其他位置的事实,而const_cast
现在以静默方式剥离它们。
在需要添加const
的情况下,它的使用很危险,难以推理。
在某些情况下,您需要致电const_cast
以便添加不会隐式发生的const
。
void assign_ptr( int const*& lhs, int const* rhs ) { lhs = rhs; }
int const foo = 7;
int* bar = nullptr;
assign_ptr( const_cast<int const*&>(bar), &foo );
*bar = 2; // undefined behavior!
std::cout << foo << "@" << &foo << "\n"; // will print probably 7@something
std::cout << *bar << "@" << bar << "\n"; // will print probably 2@same address as above!
以上对assign_ptr
的调用只会添加const
,但不会隐式发生。
它的副作用是*bar
的修改是未定义的行为,因为它修改了一个声明为const
的变量(它使bar
,int*
,指向foo
一个const int
)。
因此,虽然需要const_cast
来进行assign_ptr
调用编译,但是因为它不安全。 const_cast
不会使它更安全,它只是隐藏错误。
这是矩形平方问题的特定情况。正方形不是矩形,因为如果更改正方形的宽度,其高度也会发生变化,修改矩形时不会发生这种情况。同样,int**
不是int const**
。 (注意,不可变的Square是一种不可变的Rectangle;它是导致问题的突变。在指针的情况下,int*const*
是int const*const*
:“更高级别”指针的可变性导致问题。)