简体   繁体   中英

Is this a valid use of const_cast?

In the sample code, calling message() will never affect the contents of the class, so I'd like the method to be const . But I don't want the return value also to be const , so is it safe to use const_cast as below? or is there a better solution?

EDIT: Sorry.. so n_ is a pointer!

EDIT2: I finally managed to re-produce the problem correctly. What if n_ is an array as in int n[100] ? Then I do see a problem without const_cast .

class A
{
private:
    int n_[10];

public:
    /* ... */

    int* n() const
    {
        return const_cast<int*>(n_);
    }
};

Returning a type (not a reference) will make a copy of the object you're returning. Thus there's no need to cast it, the copy can be changed without affecting the original. The code will compile cleanly if you remove the const_cast .

Edit: based on the latest edit to the question, I'd say this is an abuse of const_cast . The principle followed by C++ is that a const member function should not only make no changes to the object itself, but should not return anything that could be used to make changes outside of the function. By returning a non-const pointer to a member variable, you violate this principle.

No, that is not a valid use of const_cast .

Your function is not modifying the array, but it is granting rights to modify the array to the caller. As such, it should have those rights itself. You can't give someone access to something which you yourself don't have access. So the method should not be const, and the const cast is then unnecessary.

You might also want a const version of the function, which returns a const int* . This is the same principle as, for example, std::vector::operator[] . Even though the operator doesn't modify the vector, it grants access to modify the vector, and so it is not a const function. (but there is also a const overloaded version, which returns a const reference, thereby not granting the right to modify the vector)

you can just return n_ , as it is

int n() const
{
    return n_;
}

There is no need for using a cast. In the function, this->n_ is a const pointer it does not point to const int .

int* n() const
{
    // No need for a cast.
    return n_;
}

It makes more sense to return a const int* from the const function. You don't want something like this:

const A a;
a.n()[0] = 10;

That subverts the const -ness of the object. You can prevent that by using:

const int* n() const
{
    // No need for a cast either.
    return n_;
}

Generally speaking, casting a T const to a T with const_cast<> is almost always unnecessary. This is because the constant object is being converted into a non-constant temporary, and this can be safely accomplished without a cast.

int const n;   // n is a constant int
int x = n;     // perfectly safe

This is true even if T is a pointer type.

int * const n; // n is a constant pointer to an int
int * x = n;   // perfectly safe

However, if you move the const keyword to the front, it is no longer making the pointer type constant, but the type that is being pointed to constant. Thus, for our example above:

const int * n; // n is a pointer to a constant int
int * x = n    // error, x is a pointer to an int

You can see that x points to a something different than what n points to, and so the initialization will fail. In this case, the initialization would require a const_cast<> :

int * x = const_cast<int *>(n);
               // cast away the const-ness that n is pointing to

You should only do this if you know that n is actually modifyable (it may not be if the pointer is to actual read-only memory), or if you know that the user of x will not actually try to modify the contents pointed to by n .


For your example, you seem to believe your const method should return a pointer to data held by your object in such a way that the data be modifiable by the caller. That is, since the n() method is declared const , it means the contents of the object being accessed should be considered constant. Thus, n_ is an array of constant int , which will decay to a pointer to constant int , but you want to return a pointer to int .

If you intend n_ to be modifiable regardless of whether the object is being treated as constant, you can declare that intention with the use of mutable . This will make n_ be treated as non-constant even if the containing object is const , and it thus makes the const_cast unnecessary.

class A
{
private:
    mutable int n_[10];

public:
    /* ... */

    int* n() const
    {
        return n_;
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM