const成员和operator =

时间:2014-12-31 13:32:22

标签: c++ stl const

我有structconst个变量

struct HashData
{
    const HashKey key;
    const void* data;
    HashData(const HashKey& key_, const void* data_) : key(key_), data(data_) {}
    /* How to write this ?
    HashData operator=(const HashData & data)
    {
        key = std::move(data.key);
        return *this;
    }
    */
};

和我使用它的另一个类。

class HashTable
{
    std::vector< std::list<HashData> > hashTable; ///< Collisions resolution by chaining.
    public:
    void insertAtIndex(const std::size_t index, const HashData& data) {
        hashTable[index].insert(std::begin(hashTable[index]), data);
    }
};

HashTable编译但是另一个类

class OpenAddressHashTable 
{
    std::vector<HashData> hashTable;
    public:    
    void insert(const HashData & data) throw() {
        if (data.key == NULLKEY)
            throw std::runtime_error("Do not use NullKey");

        size_t iteration = 0;
        do {
            const size_t index = (*hashFunc)(data.key, iteration);
            if (hashTable[index].key == NULLKEY) {
                // space is free
     // ** IMPORTANT **///// Line 131 is next line 
                hashTable[index] = data;
                return ;
            }
            iteration++;
        } while(iteration < hashTable.size());

        throw std::runtime_error("No space left");
    }
 };

我收到此错误:

g++ -W -Wall -pedantic -std=c++11 hash.cpp 
hash.cpp: In member function 'void OpenAddressHashTable::insert(const HashData&)':
hash.cpp:131:24: error: use of deleted function 'HashData& HashData::operator=(const HashData&)'
hash.cpp:26:8: note: 'HashData& HashData::operator=(const HashData&)' is implicitly deleted because the default definition would be ill-formed:
hash.cpp:26:8: error: non-static const member 'const HashKey HashData::key', can't use default assignment operator

std::list我需要将数据放入向量中是什么意思? 我是否需要在hashTable使用指针?

3 个答案:

答案 0 :(得分:3)

编译器删除类HashData的赋值运算符,因为它具有常量字段(键和数据)。这是有道理的,因为你不能为const成员分配东西,因此对象是const成员生活不应该被分配以太。 您的HashData类是不可变的。如果您希望类是这样,那么这可能没问题,但由于inmutability,无法执行类OpenAddressHashTable中的赋值。

关于你的&#34; const void * data&#34;字段:真的更像C ++就像在这里使用泛型。

你可以这样做:

template<typename T>
struct HashData
{
    HashKey key; // delete the const if you really want to modify a instance of HashData
    T data;
    HashData(const HashKey& key_, T data_) : key(key_), data(data_) {}

};

T将是您映射值的类型。这可能会迫使您所有的值都具有相同的类型,这可能不是问题。

答案 1 :(得分:2)

你正在做作业:

hashTable[index] = data;

如果您拥有const成员,则根本无法使用,因为您无法复制或迁移到const。编译器错误非常明确:

  

[赋值运算符]被隐式删除,因为默认定义是错误的

您希望分配对keydata做什么?最简单的方法是删除const并在用户界面上强制执行 - 这样他们就无法从你下面更改密钥。例如:

using InternalHashData = std::pair<HashKey, void*>; 
using ExternalHashData = std::pair<const HashKey, void*>;

InternalHashData& something_to_be_returned = ..; // never expose this
return reinterpret_cast<ExternalHashData&>(something_to_be_returned); // this is OK

我能想到保持 const的唯一方法就是改变你的表:

std::vector<HashData> hashTable;

std::vector<std::unique_ptr<HashData>> hashTable;

但是你要在每个插页上进行额外的分配只是为了保留const - ness,这对我来说似乎不是一个很好的权衡,特别是对于一个单独的容器目的是表现。

答案 2 :(得分:1)

hashTable[index].insert(std::begin(hashTable[index]), data);

将在索引处保存的链接列表的前面插入新的HashData对象。这意味着对复制构造函数的调用,默认情况下为HashData定义。 (默认的复制构造函数复制构造其所有成员,const成员是可复制的,因为您设置的是初始值,而不是覆盖现有的成员)

hashTable[index] = data;

将分配给现有的HashData对象,但默认情况下会为HashData删除分配。 (它的所有成员都是不可分配的,因为你已将它们全部声明为const

您可以做的是让HashData的成员为非const,但只返回 const引用和const迭代器到{{1}中的私有向量}}。这会将OpenAddressHashTable个对象保持为HashData,除非实际管理它们,这似乎是您的目标。