typedef std::vector <const void *>

Pages: 12
Dear Sir,

I have defined a pointer ptr2 as follows:

const void * ptr2 ( new A(20) );

In this case I expect the data pointed by ptr2 must be constant.
But when running the program, the data could still be changed successfully. Why ?

Below is the program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

// http://www.cprogramming.com/reference/pointers/const_pointers.html

class A
{
    public:
        A( int ID )
         {
             cout << "--Constructor with ID=" << ID << endl;
             this->ID = ID;
         }

       ~A() { cout << "-~Destructor with ID=" << ID << endl; }

        int getID() const { return this->ID; }

        void setID(int ID)  { this->ID = ID; }

    private:
        int ID;
};


int main()
{
    const void * ptr2 ( new A(20) );

    A *x = (A*) ptr2;
    cout << "ID of ptr2 is " << x->getID() << endl;

    x->setID(21);

    A *y = (A*) ptr2;
    cout << "ID of ptr2 is " << y->getID() << " after changed!"<< endl;
    delete y;

    cout << "End of main()" << endl;
    return 0;
}


The output:
--Constructor with ID=20
ID of ptr2 is 20
ID of ptr2 is 21 after changed!
-~Destructor with ID=21
End of main()

Process returned 0 (0x0)   execution time : 0.002 s
Press ENTER to continue.


Question
What is the significance of "const" in const void * ?
Last edited on
what you want is not const void *:
const void * and void const* both mean that the pointer is constant (you cannot change the address to which it is pointing)
You should use: void * const or both (const void* const)
However even this is wrong I don't think you can do what you want (don't let ID of ptr2 being changed since you are changing it by a non constant pointer)
the const is only for the pointer you are using unless I don't know about it
Last edited on
JewelCpp: You have your const business backwards...

1
2
3
4
const void* x; // pointer=nonconst, data=const
void const* x; // pointer=nonconst, data=const
void* const x; // pointer=const, data=nonconst
const void* const x;  // pointer=const, data=const 


The easy way to remember is to read pointer declarations 'backwards', with the "*" pronounced as 'pointer to'. Ie:

void* const is a "const pointer to a void"
const void* is a "pointer to a void const"
const void * const is a "const pointer to a void const"


@OP:
What is the significance of "const" in const void * ?


const here does not necessarily mean the data is const. It means the data cannot be changed through that pointer.

Notice you are never changing the state of the object through your 'ptr2' pointer. You are changing it through other (non-const) pointers.

You are accomplishing this by casting away the const on lines 30 and 35, thus giving you a non-const pointer.

 
A *x = (A*) ptr2;  // <- taking a const pointer and casting to a non-const pointer.  Bad! 



Also note that it is usually a very bad to do this, as it sidesteps const expectations of the compiler and may give you unexpected results.
const refers to the identifier to its left, the exception being that the first identifier can have const to its left.

1
2
3
4
5
6
7
8
9
10
int const x;         // constant integer
int const * x;       // constant integer, non-const pointer
int const * const x; // constant integer, constant pointer
int * const x ;      // non-const integer, constant pointer

// Or to write the same thing more familiarly
const int x;
const int *x;
const int * const x;
int * const x;
Last edited on
Dear all above,

I've modified this program by changing line 28 above to const void * const ptr2 ( new A(20) );
, the result doesn't change. Means the keyword "const" still has no significance at all.

The complete program is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

// http://www.cprogramming.com/reference/pointers/const_pointers.html

class A
{
    public:
        A( int ID )
         {
             cout << "--Constructor with ID=" << ID << endl;
             this->ID = ID;
         }

       ~A() { cout << "-~Destructor with ID=" << ID << endl; }

        int getID() const { return this->ID; }

        void setID(int ID)  { this->ID = ID; }

    private:
        int ID;
};


int main()
{
    const void * const ptr2 ( new A(20) );

    A *x = (A*) ptr2;
    cout << "ID of ptr2 is " << x->getID() << endl;

    x->setID(21);

    A *y = (A*) ptr2;
    cout << "ID of ptr2 is " << y->getID() << " after changed !"<< endl;
    delete y;

    cout << "End of main()" << endl;
    return 0;
}


Output of the program:
--Constructor with ID=20
ID of ptr2 is 20
ID of ptr2 is 21 after changed !
-~Destructor with ID=21
End of main()

Process returned 0 (0x0)   execution time : 0.002 s
Press ENTER to continue. 


Please note that the ID (data) pointed by ptr2 still can be changed, although the keyword "const" is used.


Question
What is the significant difference between void * and const void * ?
It seems no different whether we put in the keyword "const" or not.

But in gnuradio these two are used differently:
gr_vector_void_star and gr_vector_const_void_star

Please advise, thanks.
Last edited on
@Disch, @Lowest0ne
Thanks for the "backward" thing, that would be very helpful to memorize "the const thing", const pointer,const function, const function pointer, const function parameter... Oh there are so many consts!
28
29
30
31
32
33
const void * const ptr2 ( new A(20) );

A *x = (A*) ptr2;
cout << "ID of ptr2 is " << x->getID() << endl;

x->setID(21);

On line 33, when you use x to modify the object, x is not a const pointer.
The only const pointer in here is ptr2. However, on line 30, you "cast away" the const-ness of it when you initialize x.

If you had instead written this:
28
29
30
31
32
33
const void * const ptr2 ( new A(20) );

const A * const x = (const A* const) ptr2;
cout << "ID of ptr2 is " << x->getID() << endl;

x->setID(21); // Error: trying to call a non-const member function with a const pointer 

As you can see, the problem with C-style casts is that unsafe conversions like what you did will sometimes slip past the compiler without even a warning and possibly end up in unexpected/undefined behavior. It might be better if you try to stay away from C-style casts and use static_cast etc. instead, since static_cast will catch you if you try to do anything funny (like circumvent the const-ness of an object):
28
29
30
31
32
33
const void * const ptr2 ( new A(20) );

A *x = static_cast<A*>(ptr2); // Error: casting away const qualifiers
cout << "ID of ptr2 is " << x->getID() << endl;

x->setID(21);

And if you really want to bypass the const-ness of an object, you can use const_cast:
28
29
30
31
32
33
const void * const ptr2 ( new A(20) );

A *x = const_cast<A*>(static_cast<const A* const>(ptr2));
cout << "ID of ptr2 is " << x->getID() << endl;

x->setID(21);

Note, though, that if you ever find yourself wanting/having to use const_cast, you might want to rethink what you're actually trying to accomplish.
@long_double_main;
Thanks for the explanation, but this does not answer the question.
You explained how to cast away the const-ness, but what I want is to automatically (not explicitly) remains the const-ness.


Gnuradio (www.gnuradio.org) defines these data types:
1
2
typedef std::vector <void*>          gr_vector_void_star;
typedef std::vector <const void *>   gr_vector_const_void_star


Question
How to make sure the data pointed by gr_vector_const_void_star won't be accidently modified? Remember the purpose of const is to make sure it will not be modified accidently. This is the purpose of having gr_vector_const_void_star even though we already have gr_vector_void_star.

We know that in all cases the void pointer cannot be dereferenced directly, so we must cast it to something first before using it. Example:

1
2
3
4
5
void * ptr1 ( new A(10) );
A * x = (A*) ptr1;

const  void * ptr2 ( new A(20) );
const A * y = (A*) ptr2;


The intention is to find a way to prevent below from happening unintentionally:
(we try not to loss the const-ness of ptr2)
1
2
const  void * ptr2 ( new A(20) );
A * y = (A*) ptr2;


We do not want to loss the const-ness of ptr2, that's why we defined ptr2 as const void * rather than void *
But if the const-ness of ptr2 cannot be copied to y automatically (not explicitly), then it makes no difference whether we define ptr2 as either const void * or void *.

There must be a way to solve this. How?
Last edited on
I don't understand your problem. If you don't want to cast away the const qualifier, then simply don't cast away the const qualifier.
As long double main already showed, you can use `static_cast' to issue an error if you "accidentally" try to cast away the const qualifier.
I don't want to cast away the const qualifier, this is my purpose.
But the const qualifier lost by itself at this command:
1
2
const void * const ptr2 ( new A(20) );
A *x = (A*) ptr2;


Remember we are talking about void pointer, not any other pointer.
So, we cannot perform this:
1
2
void * ptr2 ( new A(20) );
ptr2->setID(21);


That's why we must cast ptr2 to y.
But how to remain the const qualifier of ptr2 automatically, so that it makes a difference whether ptr2 is earlier defined as either void * or const void *.

Hope you understand the question.
Last edited on
┬┐lost by itself? you were commanding it to do it.

stop doing `reinterpreter_cast' and start using `static_cast'
The thing is, if you do
1
2
const void* ptr2(new A(20));
A* y = (A*)ptr2;

then you've already casted away the const-ness of ptr2 by declaring y as a A* instead of a const A*.

That's why I suggested to use static_cast instead of C-style casts (which is what you see above), since static_cast will prevent you from casting away the const-ness like that:
1
2
3
const void* ptr2(new A(20));
A* y = static_cast<A*>(ptr2); // Error: casting away const qualifiers
const A* y2 = static_cast<const A*>(ptr2); // Fine, it's still const 

But if you stick with the C-style casts like the first example, it's just like doing this:
1
2
3
4
const void* ptr2(new A(20));
const A* tmp = static_cast<const A*>(ptr2);
A* y = const_cast<A*>(tmp);
// (or maybe it's just a reinterpret_cast, I'm not sure) 

and now you've basically told the compiler that "Hey, I know that ptr2 is const, but I want you to 'un-const' it for me anyways."
Basically speaking, if you use the C-style casts, you're asking for it and the compiler can't (won't) stop you since that's what you apparently really want.

So I would use static_cast instead.
Ok, let's put the problem in this way:

Now I need to define ptr1 and ptr2 as void pointers.
Whether the data it points to is "const" or not, this must be declared during the declaration of the pointers.
How to accomplish this ?
Now I need to define ptr1 and ptr2 as void pointers.
Whether the data it points to is "const" or not, this must be declared during the declaration of the pointers.
How to accomplish this ?

Um... by declaring them as const? Sorry, I don't understand the question.
Means,
ptr1 is a void pointer that points to a data that can be changed.
ptr2 is a void pointer that points to a data that cannot be changed.

How to accomplish this?
Haven't Disch and Lowest0ne already explained this?

To quote from Disch's post above:

1
2
3
4
const void* x; // pointer=nonconst, data=const
void const* x; // pointer=nonconst, data=const
void* const x; // pointer=const, data=nonconst
const void* const x;  // pointer=const, data=const  
Well, void data cannot be accessed (without cast), so const void has no further significance.

if you want a pointer to A why not writing:

const A* ptr2(new A(20));

?
int a;
int*ptr=&a;
const int *ptr2=ptr;

from above statements its clear that both ptr and ptr2 are pointing to the same location.But ptr can change its contents while ptr2 cant.

when we write "const int *ptr2" it doesnt mean that I cant change the contents ptr2 is pointing to ,it means that we cant change the contents ptr2 is pointing through ptr2 alone.

In the program you mentinoed, like everybody pointed out ,its kind of an illegal cast.
Thanks, I think coder777 above get the point, as he wrote:
Well, void data cannot be accessed (without cast), so const void has no further significance.


As const void has no further significance, why gnuradio defines these two separately:
1
2
typedef std::vector <void*>          gr_vector_void_star;
typedef std::vector <const void *>   gr_vector_const_void_star

Gnuradio should have defined the first one, the second one is just same with the first one, right?
(since the second one has no further significance, we can just use the first one and don't need to define the second one).

This is the question that I am trying to ask.
Last edited on
Pages: 12