开发者

Correct usage(s) of const_cast<>

As a common rule, it is very often considered a bad practice to use const_cast<>() in C++ code as it reveals (most of the time) a flaw in the design.

While I totally agree with this, I however wonder what are the cases were using const_cast<>() is ok and the only solution.

Could you guys please give me some examples you开发者_StackOverflow中文版 know/you encountered ?

Thank you very much.


it is pretty much designed to be only used with legacy APIs that are not const correct i.e. with a function you can't change that has non const interface but doesn't actually mutate anything on the interface


Like others have said, its primary purpose is to remove const from objects in order to pass to non-const correct functions you know won't modify the argument.

There is a trick (by Meyers?) to avoid code duplication, and it goes like this:

struct foo
{
    const return_type& get(void) const
    {
        // fancy pants code that you definitely
        // don't want to repeat

        return theValue; // and got it
    }

    return_type& get(void)
    {
        // well-defined: Add const to *this,
        // call the const version, then
        // const-cast to remove const (because
        // *this is non-const, this is ok)
        return const_cast<return_type&>(static_cast<const foo&>(*this).get());
    }
};


const_cast is also used to remove volatile modifiers, as put into practice in this (controversed) article:

http://www.drdobbs.com/184403766


I agree with your statement that its normal use is because you need to hide a 'design flaw'.

IME one of the typical usage scenarios is when you try to interface C++ to existing C code. A lot of existing C code takes C strings as char * even when the string is not modified whereas they're usually represented as something that converts to a const char * in C++. That's an impedance mismatch between the two languages that you would normally solve by using a const_cast. Of course you'd better be very sure that the code you're interfacing with doesn't get any cute ideas about modifying the data that's being passed in.

I would say that it's a code smells in newly written code, but for interfacing with older C and C++ code, it's an necessary evil. That said, I would be extremely wary of code that requires const_cast for any non-POD objects as that is normally a problem that should be solved at the design level and not the code level.


One legitimate use (in my opinion) is with std::set iterators. They are always const, in order to prevent changing the key used in the set. Changing the key would break the internal structure of the set and cause undefined behavior.

However, as long as the key doesn't change it's safe to change other data in the object.

Let's say you have an std::set like this:

std::set<MyObject> some_set;

And a class like this:

class MyObject {
    public:
        MyObject(const std::string &key)
            : key_(key) {}

        bool operator<(const MyObject &other) const {
            return key_ < other.key_;
        }

    private:
        // ...
        // <some other data>
        // ...

        const std::string key_;
};

In the above example, the key is already const, so even if you modify the object, you cannot break the internal structure of the set.

Normally you can only get a const reference out of a set iterator:

const MyObject &object = *some_set_iterator;

But since the key is const, it's safe to const_cast the dereferenced iterator:

MyObject &object = const_cast<MyObject &>(*some_set_iterator);


One very legitimate use of this is when you have both a const and non const api (for const and non const objects respectively) as in

class Bar {
   const SomeType& foo() const; 
   SomeType& foo();
}

Then since we don't want to duplicate the code in both functions we often use

class Bar {
   SomeType& foo() {
      //Actual implementation 
   }
   const SomeType& foo() const {
        return const_cast<Bar*>(this)->foo();
   }
};

This is of course assuming that foo does not do something that violates the const semantics.


Yes of course, when your calling code that you can't modify and isn't const correct. It should be noted that you should only use it with calls to functions that you know for certain won't modify your data!


There is an example of const_cast usage in c++ primer(5th edition) book. Below function returns reference to const string

// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}

The book then mentions the case when we want a non const reference.

We can call the function on a pair of nonconst string arguments, but we’ll get a reference to a const string as the result. We might want to have a version of shorterString that, when given nonconst arguments, would yield a plain reference. We can write this version of our function using a const_cast:

string &shorterString(string &s1, string &s2)
{
    auto &r = shorterString(const_cast<const string&>(s1),
                            const_cast<const string&>(s2));
    return const_cast<string&>(r);
}

This version calls the const version of shorterString by casting its arguments to references to const. That function returns a reference to a const string, which we know is bound to one of our original, nonconst arguments. Therefore, we know it is safe to cast that string back to a plain string& in the return.

According to the book, it should be used if we know it is safe to cast.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜