C++ C++;使用指向非常量的指针写入常量向量

C++ C++;使用指向非常量的指针写入常量向量,c++,pointers,vector,constants,C++,Pointers,Vector,Constants,我正在编写一个CustomVector类,使用标准向量在内部存储数据: template <class T> class CustomVector { friend class CustomVector_ref<T>; public: ... private: std::vector<T> _data; }; 模板 类自定义向量{ 朋友类自定义向量\u ref; 公众: ... 私人: std::vector_数据; }; 然后

我正在编写一个CustomVector类,使用标准向量在内部存储数据:

template <class T>
class CustomVector {
  friend class CustomVector_ref<T>;

  public:
  ...

  private:
    std::vector<T> _data;
};
模板
类自定义向量{
朋友类自定义向量\u ref;
公众:
...
私人:
std::vector_数据;
};
然后,为了从CustomVector中提取子向量,我使用一个类来存储指向每个数据元素的指针:

template <class T>
class CustomVector_ref {
  public:
    //Returns the value stored in CustomVector 
    //and pointed-to by _data_ref
    T& operator[] (size_t id) { return *_data_ref[id] } 
    const T& operator[] const (size_t id) { return *_data_ref[id] } 
  ...
  private:
    std::vector<T*> _data_ref;
};
模板
类CustomVector\u ref{
公众:
//返回存储在CustomVector中的值
//并由_data _ref指出
运算符[](大小\u T id){return*\u data\u ref[id]}
常量和运算符[]常量(大小\u T id){return*\u data\u ref[id]}
...
私人:
std::矢量数据参考;
};

现在,为了说明我的问题,考虑一个简单的结构来建立一个对CuthValue

的所有元素的引用是足够的。
template<class T>
CustomVector_ref<T>::CustomVector_ref(CustomVector<T>& cv)
{
  for (T& el : cv._data)
    _data_ref.push_back(&el);
}
模板
CustomVector_ref::CustomVector_ref(CustomVector和cv)
{
对于(T&el:cv.\U数据)
_数据参考推回(&el);
}
这很好,但是如果我有一个const CustomVector,我还需要定义构造函数:

template<class T>
CustomVector_ref<T>::CustomVector_ref(const CustomVector<T>& cv)
{
  for (const T& el : cv._data)
  _data_ref.push_back(const_cast<T*>(&el));
}
模板
CustomVector_ref::CustomVector_ref(const CustomVector&cv)
{
用于(施工图和标高:cv.\U数据)
_数据参考推回(常量投射(&el));
}
这也是可行的,但是如果CustomVector_ref对象没有声明为const,那么使用非const运算符[]可以将数据写入const CustomVector对象

const CustomVector<int> cv(...) //CostumVector is somehow constructed, 
                                //that does not matter now

std::cout<<cv[0]<<std::endl;  //output 1 for example

CustomVector_ref<int> cvr(cv)

cvr[0] = 2;

std::cout<<cv[0]<<std::endl;  //now cv[0] stores 2
const CustomVector cv(…)//CostumVector是以某种方式构造的,
//现在这无关紧要了

我不太清楚你想做什么。无论
CustomVector\u ref
是用
const
还是
非const
版本的向量初始化的,您是否试图阻止修改原始向量?如果是这样,只需更改
运算符[]
的返回类型即可,如下所示:

template <class T>
class CustomVector_ref {
  public:
    ...
    const T& operator[] (size_t id) { return *_data_ref[id] } 
    const T& operator[] const (size_t id) { return *_data_ref[id] } 
  ...
};

您需要考虑一个简单的事实,即标准库容器定义了两个不同的迭代器类:
iterator
const\u iterator
。这有一个很好的理由,而你刚刚发现了这个理由是什么。你的情况完全相似。您需要实现两个不同的引用,一个可变引用和一个
const
引用。为了获得额外的信任,可变引用应该可以强制转换为
常量
引用,这样就可以将它传递给以
常量
引用为参数的函数。犹豫是否将其标记为dupe,但这与使用
CustomVector_ref
密切相关?没有一个康斯特演员需要这个way@geza这是可行的,在这种情况下,没有const_cast,就不可能像任何人所期望的那样写入const CustomVector对象。但我认为更自然的做法是将CustomVector_ref声明为CustomVector的引用,即使它是const。但是我会考虑你的建议。
template <class T>
class CustomVector_ref {
  public:
    ...
    const T& operator[] (size_t id) { return *_data_ref[id] } 
    const T& operator[] const (size_t id) { return *_data_ref[id] } 
  ...
};
#include <iostream>
#include <vector>

template <class T>
class CustomVector_ref {
public:
  CustomVector_ref(T& orig_vector) : m_vector_ref(orig_vector) {}

  auto& operator[] (size_t id) { return m_vector_ref[id]; }
  const typename T::value_type& operator[] (size_t id)  const { return m_vector_ref[id]; }

  private:
  T& m_vector_ref;
};

int main(int argc, char* argv[]) {
  std::vector<int> my_vec({1, 2, 3});
  std::cout << my_vec[0] << std::endl;

  CustomVector_ref<std::vector<int>> cv_ref(my_vec);
  cv_ref[0] = 2; // Assignment is ok; non-const cv_ref initialized with a non-const vector
  std::cout << cv_ref[0] << std::endl;  //now cv[0] stores 2

  CustomVector_ref<const std::vector<int>> cv_cref(my_vec);
  // cv_cref[0] = 2; // Compile error: assignment of read-only location
  const_cast<int&>(cv_cref[0]) = 2; // Explicit override of const
  std::cout << cv_cref[0] << std::endl;

  const std::vector<int> my_const_vec({1, 2, 3});
  // CustomVector_ref<std::vector<int>> cv_cref2(my_const_vec); // Compile error; non-const initialization from const
  CustomVector_ref<const std::vector<int>> cv_cref3(my_const_vec); // Ok, const initialization from const
  // cv_cref3[0] = 2; // Compile error: assignment of read-only location
  const_cast<int&>(cv_cref3[0]) = 2; // Explicit override of const
  std::cout << cv_cref3[0] << std::endl;

  return 0;
}