1

I am trying to to understand const_cast.

In the example below, items_ is a private member variable.

The method getItems() is a const method, which means that it cannot modify the member variable items_.

getItems() returns a const vector reference which means that you cannot modify the member variable items_.

My question is, is const_cast necessary here? I don't think so as I don't need to cast away constness?

#include <iostream>

class test {  
  std::vector<Item> items_;
public:
  const std::vector<Item>& getItems() const;
};

const std::vector<mv::Item>& mv::Workloads::getItems() const
{
  return const_cast<std::vector<Item>&>(items_);
}
Useless
  • 55,472
  • 5
  • 73
  • 117
black sheep
  • 329
  • 2
  • 10
  • *"which means that it cannot modify the member variable items_"* - it does not mean that. `const_cast` here makes no sense because you first remove `const` qualifier from reference but then immediately add it back when returning that reference from function. – user7860670 Jun 19 '19 at 09:52
  • I didnt really understand why you think the cast is needed, please eloborate, if the answer does not yet convince you – 463035818_is_not_a_number Jun 19 '19 at 10:04
  • @VTT: _"'which means that it cannot modify the member variable items' - it does not mean that"_ That's exactly what it means. A member function qualified with `const` has only `const` access to data members. – Lightness Races in Orbit Jun 19 '19 at 11:38

2 Answers2

5

It is not only unnecessary but it is plain wrong in that place.

Consider what happens when you remove the const from the return type:

/*const*/ std::vector<mv::Item>& mv::Workloads::getItems() const
{
return const_cast<std::vector<Item>&>(items_);
}

Now the method returns a non-const reference to a const object! Note that the method itself is declared as const, hence this is const in the context of this method and also items_ is const. Using the reference returned by that method would lead to undefined behaviour when the method is called on a const test instance.

In that sense, the only effect of the const_cast here is to potentially silence an important compiler error should you ever decide to change the return type.

On the other hand, in the method as is (ie returning a const reference) there is no reason for the cast. items_ is const and a const reference to it is returned.

const_cast is useful eg to avoid code duplication for const and non-const methods when you do know for sure that the object you cast const away really is not const, see here for details.

PS: in case you actually do want to return a mutable reference to a member from a const method, you would declare the member mutable. Also then no const_cast would be required. Though, mutable should be used with care and usually isnt needed in the first place.

463035818_is_not_a_number
  • 64,173
  • 8
  • 58
  • 126
  • If it's really necessary for a `const` member function to return a non-`const` reference to a member, then that member can be made `mutable`. No need to muck around with `const_cast` at all - and it reduces the risk of introducing undefined behaviour. Of course, the circumstances where it makes sense to return a non-`const` reference to a member from a `const` function are pretty uncommon in practice. – Peter Jun 19 '19 at 10:58
  • @Peter yes, the example is rather contrived, and `mutable` would be the way to go, no reason for `const_cast`, no risk of ub, though the question wasnt really about how to return a mutable ref from a `const` method, so I didnt go into more detail in the answer – 463035818_is_not_a_number Jun 19 '19 at 11:22
  • @Peter added a PS to clarify – 463035818_is_not_a_number Jun 19 '19 at 11:25
3

It is not neccessary, simply return the _items.

Const member functions see the the object itself (*this) as const, so every data member is seen as const, from which building and returning const reference is allowed.

#include <iostream>
using namespace std;
class test {

std::vector<Item> items_;
public:
const std::vector<Item>& getItems() const;
};
const std::vector<mv::Item>& mv::Workloads::getItems() const
{
return items_;
}
Lorlin
  • 820
  • 5
  • 14
  • Furthermore, binding a const reference to a non const object would also be allowed, so it doesn't really matter whether the object is const or not. – eerorika Jun 19 '19 at 10:17