当类用作映射值时,复制构造函数不起作用

copy constructor doesn't work when the class is used as a map value

本文关键字:复制 构造函数 不起作用 映射      更新时间:2023-10-16

我找不到一个更简单的方法来解释我的问题,而不是直接粘贴在这里(一个简化的版本)。我有一个模板化类与必要的赋值运算符,默认构造函数和common复制构造函数。当我尝试在我的代码中使用该类时,我得到如下错误:

#include<map>
#include<vector>
template<class T>
class BufferContainer
{
public:
    BufferContainer& operator=(BufferContainer& other)
    {
        buffer = other.get();
        return *this;
    }
    BufferContainer( const BufferContainer& other ) :
        buffer( other.get() )
     {
     }
    BufferContainer(){
    }
    std::vector<T>& get() {
            return buffer;
    }
    void add(T value) {
        buffer.push_back(value);
    }
    std::vector<T> buffer;
};
int main()
{
    std::map<int, BufferContainer<int> > myMap;
    myMap[1].add(1);
    return 1;
}

,错误是:

Practice $ g++ template.cpp 
template.cpp: In instantiation of ‘BufferContainer<T>::BufferContainer(const BufferContainer<T>&) [with T = int; BufferContainer<T> = BufferContainer<int>]’:
/usr/include/c++/4.7/bits/stl_pair.h:105:31:   required from ‘std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = const int; _T2 = BufferContainer<int>]’
/usr/include/c++/4.7/bits/stl_map.h:458:11:   required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = BufferContainer<int>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, BufferContainer<int> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = BufferContainer<int>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’
template.cpp:38:9:   required from here
template.cpp:16:26: error: passing ‘const BufferContainer<int>’ as ‘this’ argument of ‘std::vector<T>& BufferContainer<T>::get() [with T = int]’ discards qualifiers [-fpermissive]

如果你帮我解决这个问题的方法,我会很感激,更重要的是,告诉我为什么我得到这个错误。由于

您的get()函数不是const限定的,并且您正在通过复制构造函数中对const的引用来调用它:

BufferContainer( const BufferContainer& other ) :
//               ^^^^^
    buffer( other.get() )
//          ^^^^^^^^^^^
{
}

这就是编译器报错的原因。不能通过引用const来调用非const函数。引用const意味着您不打算修改被引用对象的状态,因此您只能调用承诺不修改对象状态的函数。这就是成员函数上的const限定符的作用——做出这样的承诺。

因此,成员函数get()应该限定为const,并返回对const向量的引用:
std::vector<T> const& get() const 
//             ^^^^^        ^^^^^
{
    return buffer;
}

如果你需要你的非const函数get(),因为你想让客户端修改内部的buffer(建议:考虑这是否真的是一个好主意),那么你将不得不提供两个 get()的重载:

  • 一个const限定的,返回对const向量的引用(如上所示)
  • const限定的,返回对可修改向量(如原始get())的引用

这意味着您应该提供get()方法的const版本:

const std::vector<T>& get() const 
{
    return buffer;
}

,因为复制构造函数正确地接受const引用:

BufferContainer( const BufferContainer& other )

这意味着你只能在other上调用const方法。

注意返回类型是const版本,get()const引用。

other作为const的引用,get为非const方法。不能从const引用中调用非const方法