问题
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:
it's unnecessary.
T*
converts implicitly toconst T*
. Your question states thatchar sourcebuffer[] = {0x00}; copyfunction(sourcebuffer);
is an error, but that's not true.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 ifsourcebuffer
were declared asvolatile sourcebuffer[]
.
回答2:
You should not use const_cast
to add const
because
In the cases where the operation is safe, it is almost always not required.
int*
turns into aconst int*
implicitly.It can do something you don't want it to do. It can strip
volatile
, or make you miss the fact thatconst
was added somewhere else in your variables and yourconst_cast
now silently strips them.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