Reputation: 313
I have a simple Vector
class with indexing operator implemented.
Coming from this and other related questions, I am unsure as to why the following code compiles:
int main()
{
const Vector A(5);
cout << "A :" << A << endl;
A[0] = 5;
cout << "A: " << A << endl;
}
Vector.h
#pragma once
#include <iostream>
#include <functional>
namespace vector
{
class Vector
{
friend std::ostream& operator<<(std::ostream&, const Vector&);
int n;
int *arr;
public:
Vector(int = 0);
~Vector();
Vector(const Vector&);
Vector& operator=(const Vector&);
private:
void copy(const Vector&);
public:
int& operator[](const int) const;
};
}
Vector.cpp
#include "Vector.h"
#include <algorithm>
#include <utility>
#include <functional>
namespace vector
{
Vector::Vector(int n) : n(n), arr(new int[n])
{
std::fill(arr, arr + n, 0);
}
Vector::~Vector()
{
n = 0;
delete[] arr;
}
void Vector::copy(const Vector& other)
{
arr = new int[n = other.n];
std::copy(other.arr, other.arr + n, arr);
}
Vector::Vector(const Vector& other)
{
copy(other);
}
Vector& Vector::operator=(const Vector& other)
{
if (this != &other)
{
this->~Vector();
copy(other);
}
return *this;
}
int& Vector::operator[](const int index) const
{
return arr[index];
}
std::ostream& operator<<(std::ostream& stream, const Vector& vec)
{
for (int i = 0; i < vec.n; i++)
stream << vec.arr[i] << " ";
return stream;
}
}
Output:
A: 0 0 0 0 0
A: 5 0 0 0 0
How could a const method returning a non-const reference (later used to change the previously const object) even compile?
Upvotes: 3
Views: 1030
Reputation: 2788
const
in a method declaration only means that the method has read only access to the instance itself (as if it receives const MyType *this
rather than MyType *this
). If arr
is a pointer to int
in your class, it will be respectively considered as int * const
when used inside a const
method. But please note that it's not the same as const int *
! That's why dereferencing it yields an int&
, not const &int
.
Upvotes: 0
Reputation: 172924
In short, it's your responsibility.
In const
member function, only the data member itself becomes const
. For arr
(which is supposed to be of type int*
) it'll become int * const
(i.e. const
pointer), not int const *
(i.e. pointer to const
); i.e. the pointer becomes const
but the pointee doesn't. So technically it's possible to return a non-const reference to the pointee, even it might not make much sense in fact.
You'd better to overload on operator[]
, like most STL containers do. e.g.
// const version
int const & Vector::operator[](const int index) const
{
return arr[index];
}
// non-const version
int & Vector::operator[](const int index)
{
return arr[index];
}
Upvotes: 11