Here is an exercise from C++ Primer 5th Edition:
Exercise 14.26: Define subscript operators for your StrVec, String, StrBlob, and StrBlobPtr classes.(P.566)
The class StrVec
compiled without any error nor warning.Below is the class body:
/**
* @brief The StrVec class a std::vector like class without template
* std:string is the only type it holds.
*/
class StrVec
{
public:
//! default constructor
StrVec():
element(nullptr), first_free(nullptr), cap(nullptr){}
// etc
//! public members
std::string& operator [](std::size_t n) {return element[n];}
const std::string& operator [](std::size_t n) const {return element[n];}
// ^^^^^
// etc
private:
//! data members
std::string* element; // pointer to the first element
std::string* first_free; // pointer to the first free element
std::string* cap; // pointer to one past the end
std::allocator<std::string> alloc;
// etc
};
When compiling the class String
, a warning was generated, as shown below:
/**
* @brief std::string like class without template
*
* design:
*
* [0][1][2][3][unconstructed chars][unallocated memory]
* ^ ^ ^
* elements first_free cap
*/
class String
{
public:
//! default constructor
String();
// etc
char operator [](std::size_t n) {return elements[n];}
const char operator [](std::size_t n) const {return elements[n];}
// ^^^^^
private:
//! data members
char* elements;
char* first_free;
char* cap;
std::allocator<char> alloc;
// etc
};
Warning from the compiler:
warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
const char operator [](std::size_t n) const {return elements[n];}
^
The compiler I was using:
gcc version 4.8.1 (Ubuntu 4.8.1-2ubuntu1~13.04)
Why is it so? Is there any significant difference between the two classes?
const char operator [](std::size_t n) const {return elements[n];}
This returns a const copy of elements[n]
, which is no use at all. You return a const when you don't want the caller changing your stuff, but since you're returning a copy here, you wouldn't be changing anything anyways.
Your first example is returning a const reference, which is what you should do here.