这是 C++ Primer 第 5 版中的练习:
练习 14.26:为 StrVec、String、定义下标运算符 StrBlob 和 StrBlobPtr 类。(P.566)
类
StrVec
编译时没有任何错误或警告。下面是类体:
/**
* @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
};
编译类
String
时,产生警告,如下图:
/**
* @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: type qualifiers ignored on function return type [-Wignored-qualifiers]
const char operator [](std::size_t n) const {return elements[n];}
^
我使用的编译器:
gcc version 4.8.1 (Ubuntu 4.8.1-2ubuntu1~13.04)
为什么会这样?两个班级之间有什么显着差异吗?
const char operator [](std::size_t n) const {return elements[n];}
这会返回 elements[n]
的 const 副本,这根本没有用。当您不希望调用者更改您的内容时,您会返回一个常量,但由于您在这里返回一个副本,因此无论如何您都不会更改任何内容。
您的第一个示例是返回 const 引用,这是您应该在此处执行的操作。
第一个版本返回对数组元素的引用。 这是否是 const 引用决定了您是否可以只读取元素的值或也可以写入元素。
第二个版本返回数组元素的副本。 如果这是故意的,你只需要
char operator [](std::size_t n) const {return elements[n];}
如果您想要
operator []
的两个重载,一个允许读取元素,另一个允许写入元素,则需要返回引用
char& operator [](std::size_t n) {return elements[n];}
const char& operator [](std::size_t n) const {return elements[n];}