What value does const void * offer over void *?

In C ++, is there any value when using const void * for an argument type for a function over void * ? Since a void * opaque, is there a risk of a change besides the fact that the user does reinterpret_cast , in which case they could make const_cast on const void * and, therefore, did anyone really buy something? I ask because I used the utility template class for generic pointers, which provided the void specialization to avoid the void & problem, but the specialization was not provided for const void , and so I wonder if it was just supervision or was it never necessary?

+7
source share
6 answers

It offers the same benefit that const offers other types of pointers: you cannot change what it points to unless you explicitly dropped const -ness. In interfaces, const void* is a sign of client code that everything you pass can be read but not written. For example, std::memcpy declared as

 void *memcpy(void *dest, const void *src, std::size_t count); 

which signals that it will read src and write to dest . Of course, if it were really implemented in C ++ (perhaps, but hardly), it should use both pointers for other types.

If you feel that it is “not buying anything,” then this const keyword does not seem to matter.

+9
source

memcpy accepts two pointer parameters, one void* and the other const void* . The second parameter can be implicitly converted from the const char* argument (or another pointer-object-object-object-object), while the first cannot.

This lack of implicit conversion - this is the value - it forces the user to consciously discard the const in the (unlikely) event that they want, rather than accidentally discard it.

Then, as part of the implementation of memcpy or a similar function, the programmer would have to const_cast or C-style cast the const void* parameter before trying to change its referand. They will be able to static_cast non-constant parameter and change its referand. What type of throw you need to write, we hope, tells you something about what you do reasonably.

I think that if your helper functions shared_ptr should specifically handle void , then they will need to handle all cv-qualified void specially. So, there are four cases: void , const void , volatile void , const volatile void . But if function users in the past tried it on shared_ptr<void> and complained that it did not work, but never tried it on shared_ptr<const void> , then perhaps the problem did not occur.

Perhaps shared_ptr<void> already quite unusual that it did not appear. Maybe a person who uses shared_ptr<void> is inclined not to give up qualifying cv qualifiers, based on the fact that whenever someone ultimately restores the correct type, they also restore the correct qualifiers.

Think about it - does shared_ptr<const void> work, or does the code in shared_ptr that calls the deleter need an implicit conversion from T* to void* ? I don’t remember if I ever used shared_ptr<const T> .

+4
source

Do not forget the "documentation value" const . Even if someone can always drop it, const serves to indicate the original intention that the indicated thing should not be changed with a pointer. const_cast (and reinterpret_cast , for that matter) should always be used with caution and should give the programmer a pause if / when they are needed.

+3
source

Well yes, there are (some) the same advantages that const always has: it documents the fact that the contents arent to be mutated.

Provide the following code:

 int const object = some_value(); some_function(&object); 

This call is compiled only if the function argument was declared as void const* , otherwise the client will need const_cast to discard the constant. Of course, we don’t want the client to have this inconvenience, and we don’t want them to lie about their data (discarding the constant).

+2
source

There is still an advantage in self-documenting code.

 store_pod(const void* data, std::size_t bytes); 

without any comments allows you to see that the data with the pointer will not be changed.

Also, note that to break this promise const function will have to execute both a const_cast and reinterpret_cast .

+1
source

As with all uses of const , it serves two purposes. When implementing the function, this will help the compiler to detect abuses that, as you may mention, can be forced and disabled using const_cast (or a C-style cast).

But const serves a second purpose, it offers a promise that the object will not be changed, and at the same time, users can pass pointers to const objects (assuming that you keep your promise), effectively allowing a wider use of your function. This can be seen in this simple example:

 void foo( const void* ); void bar( void* ); int main() { const int value = 10; foo( &value ); // correct, the function promises not to modify the value //bar( &value ); // error, this would break const correctness } 
+1
source

All Articles