Is there a legitimate use for void*?

C++

C++ Problem Overview


Is there a legitimate use of void* in C++? Or was this introduced because C had it?

Just to recap my thoughts:

Input: If we want to allow multiple input types we can overload functions and methods, alternatively we can define a common base class, or template (thanks for mentioning this in the answers). In both cases the code get's more descriptive and less error prone (provided the base class is implemented in a sane way).

Output: I can't think of any situation where I would prefer to receive void* as opposed to something derived from a known base class.

Just to make it clear what I mean: I'm not specifically asking if there is a use-case for void*, but if there is a case where void* is the best or only available choice. Which has been perfectly answered by several people below.

C++ Solutions


Solution 1 - C++

void* is at least necessary as the result of ::operator new (also every operator new...) and of malloc and as the argument of the placement new operator.

void* can be thought as the common supertype of every pointer type. So it is not exactly meaning pointer to void, but pointer to anything.

BTW, if you wanted to keep some data for several unrelated global variables, you might use some std::map<void*,int> score; then, after having declared global int x; and double y; and std::string s; do score[&x]=1; and score[&y]=2; and score[&z]=3;

memset wants a void* address (the most generic ones)

Also, POSIX systems have dlsym and its return type evidently should be void*

Solution 2 - C++

There are multiple reasons to use void*, the 3 most common being:

  1. interacting with a C library using void* in its interface
  2. type-erasure
  3. denoting un-typed memory

In reverse order, denoting un-typed memory with void* (3) instead of char* (or variants) helps preventing accidental pointer arithmetic; there are very few operations available on void* so it usually require casting before being useful. And of course, much like with char* there is no issue with aliasing.

Type-erasure (2) is still used in C++, in conjunction with templates or not:

  • non-generic code helps reducing binary bloat, it's useful in cold paths even in generic code
  • non-generic code is necessary for storage sometimes, even in generic container such as std::function

And obviously, when the interface you deal with uses void* (1), you have little choice.

Solution 3 - C++

Oh yes. Even in C++ sometimes we go with void * rather than template<class T*> because sometimes the extra code from the template expansion weighs too much.

Commonly I would use it as the actual implementation of the type, and the template type would inherit from it and wrap the casts.

Also, custom slab allocators (operator new implementations) must use void *. This is one of the reasons why g++ added an extension of permitting pointer arithmatic on void * as though it were of size 1.

Solution 4 - C++

> Input: If we want to allow multiple input types we can overload > functions and methods

True. >alternatively we can define a common base > class.

This is partially true: what if you can't define a common base class, an interface or similar? To define those you need to have access to the source code, which is often not possible.

You didn't mention templates. However, templates cannot help you with polymorphism: they work with static types i.e. known at compile time.

void* may be consider as the lowest common denominator. In C++, you typically don't need it because (i) you can't inherently do much with it and (ii) there are almost always better solutions.

Even further, you will typically end up on converting it to other concrete types. That's why char * is usually better, although it may indicate that you're expecting a C-style string, rather than a pure block of data. That's whyvoid* is better than char* for that, because it allows implicit cast from other pointer types.

You're supposed to receive some data, work with it and produce an output; to achieve that, you need to know the data you're working with, otherwise you have a different problem which is not the one you were originally solving. Many languages don't have void* and have no problem with that, for instance.

Another legitimate use

When printing pointer addresses with functions like printf the pointer shall have void* type and, therefore, you may need a cast to void*

Solution 5 - C++

Yes, it is as useful as any other thing in the language.
As an example, you can use it to erase the type of a class that you are able to statically cast to the right type when needed, in order to have a minimal and flexible interface.

In that response there is an example of use that should give you an idea.
I copy and paste it below for the sake of clarity:

class Dispatcher {
    Dispatcher() { }

    template<class C, void(C::*M)() = C::receive>
    static void invoke(void *instance) {
        (static_cast<C*>(instance)->*M)();
    }

public:
    template<class C, void(C::*M)() = &C::receive>
    static Dispatcher create(C *instance) {
        Dispatcher d;
        d.fn = &invoke<C, M>;
        d.instance = instance;
        return d;
    }

    void operator()() {
        (fn)(instance);
    }

private:
    using Fn = void(*)(void *);
    Fn fn;
    void *instance;
};

Obviously, this is only one of the bunch of uses of void*.

Solution 6 - C++

Interfacing with an external library function which returns a pointer. Here is one for an Ada application.

extern "C" { void* ada_function();}

void* m_status_ptr = ada_function();

This returns a pointer to whatever it was Ada wanted to tell you about. You don't have to do anything fancy with it, you can give it back to Ada to do the next thing. In fact disentangling an Ada pointer in C++ is non-trivial.

Solution 7 - C++

In short, C++ as a strict language (not taking into account C relics like malloc()) requires void* since it has no common parent of all possible types. Unlike ObjC, for example, which has object.

Solution 8 - C++

The first thing that occurs to my mind (which I suspect is a concrete case of a couple of the answers above) is the capability to pass an object instance to a threadproc in Windows.

I've got a couple of C++ classes which need to do this, they have worker thread implementations and the LPVOID parameter in the CreateThread() API gets an address of a static method implementation in the class so the worker thread can do the work with a specific instance of the class. Simple static cast back in the threadproc yields the instance to work with, allowing each instantiated object to have a worker thread from a single static method implementation.

Solution 9 - C++

In case of multiple inheritance, if you need to get a pointer to the first byte of a memory chunk occupied by an object, you may dynamic_cast to void*.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmagu_View Question on Stackoverflow
Solution 1 - C++Basile StarynkevitchView Answer on Stackoverflow
Solution 2 - C++Matthieu M.View Answer on Stackoverflow
Solution 3 - C++JoshuaView Answer on Stackoverflow
Solution 4 - C++edmzView Answer on Stackoverflow
Solution 5 - C++skypjackView Answer on Stackoverflow
Solution 6 - C++RedSonjaView Answer on Stackoverflow
Solution 7 - C++nredkoView Answer on Stackoverflow
Solution 8 - C++AndyWView Answer on Stackoverflow
Solution 9 - C++Minor ThreatView Answer on Stackoverflow