简体   繁体   English

使用const_cast添加const-ness - 坏主意?

[英]Using const_cast to add const-ness - bad idea?

as we all know the usage of const_cast to remove the const-ness of a pointer should be avoided. 众所周知,应避免使用const_cast来删除指针的常量。

But how is it about the other way around? 但是另一种方式呢?

For my use case I have a function that copies data (bytes) from a non-const source buffer. 对于我的用例,我有一个从非const源缓冲区复制数据(字节)的函数。 I thought a good design decision would be to declare the parameter according to that source buffer fully const. 我认为一个好的设计决定是根据源缓冲区完全const来声明参数。

void copyfunction(const char* const data) { ... }

For a function call like below this would lead to a pointer-type error 'const char* const <-> char*'. 对于像下面这样的函数调用,这将导致指针类型错误'const char * const < - > char *'。

void main() {
    char sourcebuffer[] = {0x00};

    copyfunction(sourcebuffer);
}

Sure, now I could simply declare the sourcebuffer as const but in my case I don't have access to that variable because it's from a different code location (external library). 当然,现在我可以简单地将sourcebuffer声明为const,但在我的情况下,我无法访问该变量,因为它来自不同的代码位置(外部库)。

void main() {
    char sourcebuffer[] = {0x00};

    copyfunction(const_cast<const char* const>(sourcebuffer));
}

However the code beyond would work but is it good style (according to my use case)? 然而,超出的代码可以工作,但它是好的风格(根据我的用例)?

I thought declaring the parameter of the copyfunction as const assures the user of not modifying (read-only) the pointer or the location of the source buffer itself. 我认为声明copyfunction函数的参数为​​const可以确保用户不修改(只读)指针或源缓冲区本身的位置。 So in this case the const_cast would only be a necessary evil to enable to function call and not willfully remove the const-ness of a pointer... 所以在这种情况下,const_cast只是启用函数调用的必要之恶,而不是故意删除指针的常量......

Greets 电贺

You should not use const_cast to add const , because: 你不应该使用const_cast来添加const ,因为:

  1. it's unnecessary. 这是不必要的。 T* converts implicitly to const T* . T*隐式转换为const T* Your question states that char sourcebuffer[] = {0x00}; copyfunction(sourcebuffer); 你的问题表明char sourcebuffer[] = {0x00}; copyfunction(sourcebuffer); char sourcebuffer[] = {0x00}; copyfunction(sourcebuffer); is an error, but that's not true. 是一个错误,但事实并非如此。

  2. it's potentially (albeit unlikely) harmful. 它可能(虽然不太可能)有害。 It can remove volatile from the pointer type, which is not the intention here and would result in undefined behavior if sourcebuffer were declared as volatile sourcebuffer[] . 它可以从指针类型中删除volatile ,这不是这里的意图,如果sourcebuffer被声明为volatile sourcebuffer[] ,则会导致未定义的行为。

You should not use const_cast to add const because 你不应该使用const_cast来添加const因为

  1. In the cases where the operation is safe, it is almost always not required. 在操作安全的情况下,几乎总是不需要。 int* turns into a const int* implicitly. int* const int*隐式变为const int*

  2. It can do something you don't want it to do. 它可以做一些你不希望它做的事情。 It can strip volatile , or make you miss the fact that const was added somewhere else in your variables and your const_cast now silently strips them. 它可以剥离volatile ,或者让你错过const被添加到变量中的其他地方的事实,你的const_cast现在默默地剥离它们。

  3. In the cases where it is required to add const , its use is dangerous in hard to reason about ways. 在需要添加const的情况下,它的使用很危险,难以推理。

There are cases where you need to call const_cast in order to add const that will not happen implicitly. 在某些情况下,您需要调用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!

the above call to assign_ptr only adds const , but it will not happen implicitly. 上面对assign_ptr调用只添加了const ,但它不会隐式发生。

A side effect of it is that modification of *bar is undefined behavior, as it modifies a variable declared const (it makes bar , a int* , point at foo a const int ). 它的一个副作用是*bar修改是未定义的行为,因为它修改了一个声明为const的变量(它使得bar ,一个int* ,指向foo一个const int )。

So while const_cast is required to make the assign_ptr call compile, it is because it was unsafe . 因此,虽然const_cast需要使assign_ptr调用compile, 但这是因为它不安全 The const_cast doesn't make it safer, it just hides the error. const_cast不会使它更安全,它只是隐藏错误。

This is a specific case of the rectangle-square problem. 这是矩形平方问题的特定情况。 Squares are not Rectangles, because if you change the width of a Square its height also changes, and this does not happen when you modify a Rectangle. 正方形不是矩形,因为如果更改正方形的宽度,其高度也会发生变化,修改矩形时不会发生这种情况。 Similarly, int** are not int const** . 类似地, int**不是int const** (Note that immutable Squares are a kind of immutable Rectangle; it is the mutation that causes the issue. In the case of pointers, a int*const* is a int const*const* : the mutability of the "higher level" pointers causes the problem.) (注意,不可变的Square是一种不可变的Rectangle;它是导致问题的突变。在指针的情况下, int*const*是一个int const*const* :“更高级别”指针的可变性导致问题。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM