Why is it impossible to have a reference-to-void?

后端 未结 10 946
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-23 19:32

Why is it impossible to have a reference to void? The only thing I found in the C++ Standard is this line, at 8.3.2.1

A declarator th

相关标签:
10条回答
  • 2020-12-23 20:19

    Here's a summary of the different things that have been said, and that I've thought of.

    Two main reasons why reference-to-void are disallowed


    1 They would have been totally useless.

    Indeed, if we look back at the times of C, void pointers had two purposes:

    • Memory management (e.g. malloc)
    • Genericity (writing functions that can accept any type of arguments)

    When C++ came out, templates became the best solution to implement genericity. However, custom memory management still had to be possible, and interoperability between C++ and C was a major concern, so void* was kept. An hypothetical void reference would be of no help with memory management, and genericity is already covered, so basically it would have almost no use (except for the guarantee of non-nullness described below).

    2 You wouldn't be able to do anything with it

    When using a void pointer, you're not allowed to dereference it; transposed to the case of references, that means you can't use the (always hypothetical) void reference. So

    void *data = // something
    // using *data and data-> is forbidden
    
    void &data = // something
    // using data is forbidden
    

    However, we could think of a use case where the reference wouldn't have to be "dereferenced" (this phrase is awfully incorrect, but you get my point), but where we would only take its address . Let's assume I have the following function:

    void foo(void *dataptr)
    {
        assert(dataptr != NULL); // or != 0
        // do something with dataptr
    }
    

    To avoid this annoying assert, I could write the function this way:

    void foo(void &dataref)
    {
        void *data = &dataref;
        // do something with data
    }
    

    However, for this to work, &dataref needs to be equivalent to dataptr, which is not the case: &dataref is equivalent to &*dataptr!

    Therefore, even taking the address implies a dereferencing, at least conceptually (behind the scenes, the first equivalence is probably true, but at the semantic level it is not). Consequently, there is absolutely no usage we can make of data, so void references are an aberration.

    0 讨论(0)
  • 2020-12-23 20:36

    void is something that, by definition, doesn't exist, so it is not logical to have it's adress.

    0 讨论(0)
  • 2020-12-23 20:38

    Ask your self first, how you would de-reference a void pointer?

    void *p = /*something*/ ;
    cout << *p << endl;
    

    The above code is meaningless, one of the reasons we have void is so we can say "I need to do some generic pointer work here, and I neither know nor care what I'm pointing to". By definition, the compiler doesn't know what a void * points to, therefore it can't dereference it. You can - by casting - but the compiler can't.

    A reference to a void sufferes from the same problem, by definition the data pointed to doesn't have a type, therefore it can't be referenced in any meaningful way.

    To reference it you - the programmer - need to cast it to another type, then you can have a typed reference to it.

    Not sure if I explained this as well as I wanted to.

    Ruben, any thoughts?

    EDIT: To answer your edit.

    Take the first function, where you pass void* data. data is a perfectly valid item, you can compute with it, or if you've some logging implemented, you can log it.

    logger << data;
    

    and you'll get the address data points to. If you try to dereference data, the compiler will give you an error (don't have C++ compiler handy at moment, so not sure of the actual error). e.g.

    void* data = /* some assignment */;
    logger << *data; // compiler error.
    

    Now, the compiler won't let you dereference a void* for any reason (it doesn't make sense), the same stands for a reference to void &data, except that because it's a reference it's implicitly dereferenced all the time. The compiler won't let you dereference a void* on one operation, it's not going to let you dereference it constantly.

    void& data = /* some assignment *.;
    logger << data; // means same as logger << *data above
    

    You can't do ANYTHING to data EXCEPT take it's address, and there's a perfectly good - and safe - method built into the languge to do that, i.e.

    void* data;
    

    Is this making any more sense?

    0 讨论(0)
  • 2020-12-23 20:38

    You can think of a reference as a de-referenced pointer. Syntactically you treat a reference as though it is not a pointer: you do not need the * operator to dereference it, and you can use . rather than -> to access its members.

    However, you cannot dereference a void pointer. As pointed out by Binary Worrier trying to do that will give you a compiler error. And if you cannot have a dereferenced void pointer, that means you cannot have a void reference.

    0 讨论(0)
提交回复
热议问题