Using const_cast to add const-ness - bad idea?

回眸只為那壹抹淺笑 提交于 2019-12-07 17:22:03

问题


as we all know the usage of const_cast to remove the const-ness of a pointer should be avoided.

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. I thought a good design decision would be to declare the parameter according to that source buffer fully 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*'.

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).

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. 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...

Greets


回答1:


You should not use const_cast to add const, because:

  1. it's unnecessary. T* converts implicitly to const T*. Your question states that 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[].




回答2:


You should not use const_cast to add const because

  1. In the cases where the operation is safe, it is almost always not required. int* turns into a const int* implicitly.

  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.

  3. In the cases where it is required to add const, its use is dangerous in hard to reason about ways.

There are cases where you need to call const_cast in order to add const that will not happen implicitly.

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.

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).

So while const_cast is required to make the assign_ptr call compile, it is because it was unsafe. The const_cast doesn't make it safer, it just hides the error.

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**. (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.)



来源:https://stackoverflow.com/questions/20956757/using-const-cast-to-add-const-ness-bad-idea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!