【问题标题】:const members and operator=const 成员和 operator=
【发布时间】:2014-12-31 23:59:01
【问题描述】:

我有一个 struct 和一些 const 变量

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);
    }
};

class 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 中使用指针吗?

【问题讨论】:

    标签: c++ stl constants


    【解决方案1】:

    你正在做作业:

    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】:

      编译器删除类HashData 的赋值运算符,因为它具有常量字段(键和数据)。这是有道理的,因为您不能将某些东西分配给 const 成员,因此 const 成员所在的对象不应该被分配为 ether。 您的 HashData 类是不可变的。如果您希望班级如此,这可能没问题,但由于不可变性,您的班级 OpenAddressHashTable 中的分配无法执行。

      另外关于您的“const void* data”字段:真的更像 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 将是您映射值的类型。这当然会迫使你所有的值都具有相同的类型,这可能不是问题。

      【讨论】:

      • 我的主要问题是 std::list 如何与我的 HashData 类一起工作?它如何存储此类的实例?它从不使用 = 运算符吗?
      • @AshishNegi:为什么会这样?
      • 因此,如果我从该点删除节点并在该索引处插入一个新节点,那应该可以工作..但不应该是 O(n).. 但理想情况下,因为我只是在更改该内存.. 我希望有更好的方法.. 不牺牲 constness。
      【解决方案3】:
      hashTable[index].insert(std::begin(hashTable[index]), data);
      

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

      hashTable[index] = data;
      

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

      您可以做的是将HashData 的成员设为非const,但仅将const 引用和const 迭代器返回到OpenAddressHashTable 中的私有向量。这将使您的HashData 对象在任何地方都保持为const,除了它们实际管理的地方,这似乎是您的目标。

      【讨论】:

        猜你喜欢
        • 2019-10-18
        • 1970-01-01
        • 1970-01-01
        • 2011-02-06
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 2016-12-14
        • 1970-01-01
        相关资源
        最近更新 更多