在C++中,作为类成员的引用应为常量或非常量
In C++, reference as class member shall be const or non-const
考虑以下最小示例。
#include <vector>
class Data
{
std::vector<int>& v;
public:
Data(std::vector<int>& _v) : v(_v) {}
Data(const std::vector<int>& _v) : v(_v) {} // error!
};
int main()
{
std::vector<int> v;
const std::vector<int> c_v;
Data d(v);
Data const_d(c_v);
return 0;
}
这不会编译。下面是g++ -Wall
的全部输出。
const.cpp: In constructor ‘Data::Data(const std::vector<int>&)’:
const.cpp:8:41: error: invalid initialization of reference of type ‘std::vector<int>&’ from expression of type ‘const std::vector<int>’
原因我很清楚:const关键字对我在第8行中的角色扮演感到不安。问题是:我有时确实需要带std::vector
的Data类,但有时需要带const std::vector
的Data类。比如有两个类:一个用于读入Data
,另一个用于从Data
读入。然而,我不喜欢编写两个具有几乎冗余函数的Data类。我的问题:
- 你能给我一个很好的解决方案来实现我在
main()
中尝试做的事情吗?C++11解决方案也非常受欢迎:) - 这就是
iterator
和const_iterator
的原因吗
const
-数据成员的数量需要在编译时知道。如果"有时"需要对const
向量的引用,有时需要对非const
的引用,则应该创建一个类层次结构,该类具有包含公共功能的基本抽象类,并在两个Data
类中继承它:Data
和ConstData
。Data
将包含非const
向量,而ConstData
将包含const
向量。这样就不会复制任何逻辑,而两个独立的类将包含两个不同const
性质的引用。
这里有一个例子:
class AbstractData {
public:
// Common functions use vect() and const_vect()
void common_function1();
void common_function2();
protected:
virtual vector<int>& vect() const = 0;
virtual const vector<int>& const_vect() const = 0;
};
class Data : public AbstractData {
vector<int>& v;
public:
Data(vector<int>& _v) : v(_v) {}
protected:
vector<int>& vect() const {
return v;
}
const vector<int>& const_vect() const {
return v;
}
};
class ConstData : public AbstractData {
const vector<int>& v;
vector<int> temp;
public:
ConstData(const vector<int>& _v) : v(_v) {}
protected:
vector<int>& vect() const {
return temp; // You can choose to throw an exception instead
}
const vector<int>& const_vect() const {
return v;
}
};
注意,根据使用情况,这个类层次结构可能需要析构函数和各种复制构造函数。
您得到的错误是:
foo.cpp: In constructor ‘Data::Data(const std::vector<int>&)’:
foo.cpp:8:44: error: invalid initialization of reference of type ‘std::vector<int>&’ from expression of type ‘const std::vector<int>’
因为您正试图创建一个对数据的非常数引用,您(Data
)承诺您的调用者将被视为const
。
以下是一个将const
引用声明为Data
成员的解决方案:
#include <vector>
class Data
{
const std::vector<int> &v;
public:
Data(std::vector<int>& _v) : v(_v) {}
Data(const std::vector<int>& _v) : v(_v) {} // error!
};
int main()
{
std::vector<int> v;
std::vector<int> c_v;
Data d(v);
Data const_d(c_v);
return 0;
}
另一种选择是使用非参考成员:
#include <vector>
class Data
{
std::vector<int> v;
public:
Data(std::vector<int>& _v) : v(_v) {}
Data(const std::vector<int>& _v) : v(_v) {} // error!
};
相关文章:
- 什么时候在C++中返回常量引用是个好主意
- 通过常量引用传递参数的矩阵模板类
- 在C++中使用非常量引用作为常量
- 具有常量引用参数的函数模板专用化
- 多个"常量引用"变量可以共享同一个内存吗?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 为什么常量方法可以采用非常量引用?
- 为什么当我们有常量引用时创建临时对象?
- 如何返回向量的常量引用?
- C++:常量引用参数
- 不同于按值传递和常量引用传递的程序集
- 为什么const_cast和static_cast常量引用没有效果?
- C++ 获取函数在常量引用中按值返回的结果
- 从 BubbleSort* 类型的右值初始化 'AssortedSorter&' 类型的非常量引用无效"
- C++ 在类中使用常量引用文本时 O2 内存泄漏
- 是否可以跨 dll 边界返回常量引用/指向 std::vectors?
- C++中大多数/所有 setter 函数的参数是否应该写为常量引用?
- 通过非常量引用参数修改常量引用参数
- 将常量引用传递给线程
- 为什么C++中没有常量引用,就像常量指针一样?