0

In g++ , element access operator for const std::vector<> is defined as follows: (/usr/include/c++/7.1.1/bits/stl_vector.h)

/**
   *  @brief  Subscript access to the data contained in the %vector.
   *  @param __n The index of the element for which data should be
   *  accessed.
   *  @return  Read-only (constant) reference to data.
   *
   *  This operator allows for easy, array-style, data access.
   *  Note that data access with this operator is unchecked and
   *  out_of_range lookups are not defined. (For checked lookups
   *  see at().)
   */
  const_reference
  operator[](size_type __n) const _GLIBCXX_NOEXCEPT
  {
__glibcxx_requires_subscript(__n);
return *(this->_M_impl._M_start + __n);
  }

But the following code compiles with no problem using g++ -c const-vector.cpp -Wall -pedantic

#include <vector>

void sum(const std::vector<int>& data){
  int *ptr;
  ptr = (int*) &data[0];
  if (data.size()>2) 
    for (unsigned int i=1;i<data.size();i++) 
      ptr[0]+=ptr[i];
return;}

So I'm changing the contents of the vector passed by const reference.

According to cppreference.com , operator[] is overloaded:

reference       operator[]( size_type pos );
const_reference operator[]( size_type pos ) const;

In which case compiler will take the second overload?

R. F. Luis
  • 99
  • 2
  • 7
  • 3
    1. You can do many dangerous things with casts, 2. It's not a problem per se to modify something that was passed by const reference. It would only be a problem if you actually passed a const object to this function. – M.M Jul 06 '17 at 23:25
  • Also your code would be UB if passed an empty vector – M.M Jul 06 '17 at 23:26
  • 2
    classic c cast is a sledgehammer - it will do whatever you say. see what happens with static_cast – pm100 Jul 06 '17 at 23:38
  • Basically all of these answers take a long way of saying that a C-style cast will perform the function of a `const_cast` (among other things). – Michael Burr Jul 06 '17 at 23:44

1 Answers1

1

On a range from "screwriver" to "table saw", the C-style cast is a mortar strike.

When the C-style cast expression is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:
a) const_cast<new_type>(expression);
b) static_cast<new_type>(expression), with extensions [...];
c) static_cast (with extensions) followed by const_cast;
d) reinterpret_cast<new_type>(expression);
e) reinterpret_cast followed by const_cast.

It will literally pile up increasingly dangerous casts until the type system bends and/or something breaks. You should use it only when you definitely, absolutely, need to disable every safety you can to perform an operation that goes outside of the normal rules of the language.

In that case, you must know exactly what you're doing, and making a mistake will pretty much always trigger UB without diagnostic (because you just told the compiler to shut up and trust you).

Forcefully modifying an unknown const object is not a good idea -- unless you can prove it has originally been declared as non-const, you're off to UB-land.

Quentin
  • 62,093
  • 7
  • 131
  • 191