简体   繁体   English

需要帮助了解C ++中的运算符重载

[英]Need help understanding operator overloading in C++

I'm trying to implement a structure which is basically a custom made hash table containing either nothing (NULL) or a pointer to a binary search tree object. 我正在尝试实现一种结构,该结构基本上是一个自定义的哈希表,其中不包含任何内容(NULL)或指向二进制搜索树对象的指针。

Anyway, I'm having trouble figuring out how to do some things, such as setting the hash table, which is an array to NULL, and also memcpy'ing BST objects from one table to another. 无论如何,我在弄清楚如何做一些事情时都遇到了麻烦,例如将哈希表(它是一个数组设置为NULL),以及将BST对象从一个表转移到另一个表。

BST *prevData;
BST *currData;

As I understand it, I think I have to overload the = and == operators to allow setting array elements to NULL, is this correct? 据我了解,我认为我必须重载=和==运算符以允许将数组元素设置为NULL,这是正确的吗? I'm really unclear about how to implement all this, but going on examples from Google, I've got: 我真的不清楚如何实现所有这些功能,但是通过Google的示例,我已经知道:

BST& BST :: operator= (int null);
bool BST :: operator== (int null);

The == operator overload is to check whether a specific array index is equal to NULL. ==运算符重载是要检查特定的数组索引是否等于NULL。 I'm assuming I need some additional code, rather than just the prototypes, and this is where I come unstuck. 我假设我需要一些其他代码,而不仅仅是原型,而这就是我无法解决的问题。

The second point is memcpy, which I'm not being allowed to do by the compiler. 第二点是memcpy,编译器不允许我这样做。

memcpy(prevData[x], currData[x], sizeof(BST) * height);

Complains about 投诉

error C2664: 'memcpy' : cannot convert parameter 1 from 'BST' to 'void *' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 错误C2664:'memcpy':无法将参数1从'BST'转换为'void *'没有可用的用户定义转换运算符可以执行此转换,或者无法调用该运算符

If you need more information, I'd be happy to fill you in. 如果您需要更多信息,我们很乐意为您填写。

Any clues? 有什么线索吗? Thanks. 谢谢。

As I understand it, I think I have to overload the = and == operators to allow setting array elements to NULL, is this correct? 据我了解,我认为我必须重载=和==运算符以允许将数组元素设置为NULL,这是正确的吗?

No, not at all. 一点都不。 You have described an array of BST * pointers, not of BST objects. 您已经描述了一个BST *指针数组,而不是BST对象数组。 NULL is already a valid value for a pointer to take, you don't need to change any C++ behaviour: NULL已经是一个有效的指针值,您无需更改任何C ++行为:

BST *array[LENGTH]; // LENGTH > 1
array[0] == NULL;
array[0] == new BST; // but watch for memory leaks!
array[1] == array[0];
array[0] == NULL; // now moved the array[0] pointer to array[1]

Any time you have an array of pointers, memory management becomes tricky, and it becomes important to consider smart pointers such as shared_ptr . 每当您拥有一个指针数组时,内存管理就会变得棘手,考虑诸如shared_ptr智能指针就变得很重要。

EDIT: as discussed in the comments, a better solution is to have some sort of null BST value: 编辑:如评论中所述,更好的解决方案是具有某种空BST值:

class BST {
    bool isNull_;
    BST() : isNull_(true) {}
    bool isNull() { return isNull_; }
    // rest of class definition...
};

now, you have an "empty" BST value for which bst.isNull_ is true. 现在,您有一个bst.isNull_为true的“空” BST值。 The default value is a null value. 默认值为空值。 So if you create an empty vector: 因此,如果您创建一个空向量:

std::vector<BST> vec = std::vector<BST>(10);

this will initialise to 10 null BSTs. 这将初始化为10个空BST。 The same is true for the new[] array allocation operator. 对于new[]数组分配运算符也是如此。

The second point is memcpy, which I'm not being allowed to do by the compiler. 第二点是memcpy,编译器不允许我这样做。

 memcpy(prevData[x], currData[x], sizeof(BST) * height); 

Don't do that! 不要那样做! It's wrong for a number of reasons, but mainly because it's a legacy C function, not suitable for C++ classes; 有许多原因是错误的,但主要是因为它是传统的C函数,不适用于C ++类。 and because you're copying one item, not a block of them. 并且因为您要复制的是一项,而不是全部。

To copy one item, use operator= : 要复制一项,请使用operator=

currData[x] = prevData[x];

The C++ function for copying block data is std::copy . 用于复制块数据的C ++函数为std::copy One reason to use it is that it can recognise overloaded operator= assignment operators, while memcpy can't. 使用它的原因之一是它可以识别重载的operator=赋值运算符,而memcpy则不能。 Example: 例:

std::copy(prevData, prevData + LENGTH, currData);

(I assume you want to copy from prevData to currData like I've done here, rather than the other way around like you did for memcpy ?) (我假设您要像在此所做的那样, prevData复制 currData ,而不是像对memcpy那样进行其他操作?)

If it wasn't homework (that was your tag?) I'd recommend a single unordered_map or map. 如果不是家庭作业(那是您的标签?),我建议您使用一张unordered_map或map。 You're conception of this isn't coming together yet - best to simplify it and tackle one thing at a time rather than biting off more than you can chew. 您尚未意识到这一点-最好将其简化并一次处理一件事情,而不是花太多钱才能咀嚼。 If you want a hash map of trees, I suggest you start building that from the C++ STL containers that you can rely on to work, then - if you're not supposed to use them for this task - replace them one by one making sure you keep the high-level usage/tests working as you do it. 如果您想要一个树的哈希图,建议您从可以依靠它工作的C ++ STL容器开始构建,然后-如果不打算将它们用于此任务,请确保将它们一一替换您可以在执行时保持高级用法/测试。 That means: 这意味着:

typedef vector<map<T> > Container;
Container container;

You can use container.resize(n) to fill the container with n empty maps, or to grow the container from some previous size to a new one with the extra maps being empty. 您可以使用container.resize(n)在容器中填充n个空的地图,也可以将容器从以前的某个尺寸扩大到新的容器,而多余的地图为空。

Really, start with that. 真的,从那开始。 Then if you have to as an exercise, implement each of the vector and map independently, and test their usage with simple indepedent test cases before slotting them back into your hybrid hash map. 然后,如果您必须作为练习,则分别实现每个向量和映射,并在将其放回到混合哈希映射之前,使用简单的独立测试用例测试它们的用法。

It may sound like I'm being a bit harsh, so lets work through a bit of your question to see some of the mis-conceptions of which I spoke: 听起来好像我有点苛刻,所以让我们仔细研究一下您的问题,看看我所说的一些误解:

Anyway, I'm having trouble figuring out how to do some things, such as setting the hash table, which is an array to NULL, and also memcpy'ing BST objects from one table to another. 无论如何,我在弄清楚如何做一些事情时都遇到了麻烦,例如将哈希表(它是一个数组设置为NULL),以及将BST对象从一个表转移到另一个表。

My advice is keep things simple and do what's obvious and clean. 我的建议是让事情简单,做显而易见的事情。 If you must use an array and not a vector, then if it's on the stack: 如果必须使用数组而不是向量,则它在堆栈中:

X* buckets[N];
for (int i = 0; i < sizeof buckets / sizeof buckets[0]; ++i)
    array[i] = NULL;

If it's on the heap: 如果在堆上:

X** p_buckets = new X*[N];
for (int i = 0; i < N; ++i)
    array[i] = NULL;

This is slower than memset(), but it's simple and understandable, and gets you in the habit of thinking about looping over your container, doing the operations you want. 这比memset()慢,但是它简单易懂,并且使您养成了思考循环容器,执行所需操作的习惯。 There are more C++ ways to this, but it's harder to use those same styles of iteration for other arbitrary tasks, so stick to this until you're totally comfortable with it. 有更多的C ++方式,但是很难将相同的迭代样式用于其他任意任务,因此请坚持这样做直到您完全满意为止。

BST *prevData; BST * prevData; BST *currData; BST * currData;

As I understand it, I think I have to overload the = and == operators to allow setting array elements to NULL, is this correct? 据我了解,我认为我必须重载=和==运算符以允许将数组元素设置为NULL,这是正确的吗? I'm really unclear about how to implement all this, but going on examples from Google, I've got: 我真的不清楚如何实现所有这些功能,但是通过Google的示例,我已经知道:

BST& BST :: operator= (int null); BST&BST ::运算符=(int null); bool BST :: operator== (int null); 布尔BST ::运算符==(int null); The == operator overload is to check whether a specific array index is equal to NULL. ==运算符重载是要检查特定的数组索引是否等于NULL。 I'm assuming I need some additional code, rather than just the prototypes, and this is where I come unstuck. 我假设我需要一些其他代码,而不仅仅是原型,而这就是我无法解决的问题。

You've got two pointers to BSTs. 您有两个指向BST的指针。 Your hash tables are an array of such objects, but it's only one of your comment that suggests you conceive of these as pointers to two such hash tables (rather than say being temporary variables recording non-NULL elements during iteration through the hash table). 您的哈希表是这样的对象的数组,但这只是您的一条评论,建议您将这些概念视为指向两个这样的哈希表的指针(而不是说是在哈希表迭代期间记录非NULL元素的临时变量)。 They should be BST**, as they point to the first BST* in the hash table. 它们应为BST **,因为它们指向哈希表中的第一个BST *。 But, this is a very dangerous way to implement your hash tables, as the client is using a pointer to the hash table rather than a pointer to some class that provides a safe implementation of the hash table concept. 但是,这是实现哈希表的一种非常危险的方式,因为客户端使用的是指向哈希表的指针,而不是指向提供哈希表概念的安全实现的类的指针。 With such a pointer, all they can do is index to a specific BST, but there's no association with the functions that you intend to maintain the hash table, nor the variables that track how many buckets it currently has space for, how many elements it contains, etc.. You should put your arrays into a class that provides all this; 有了这样的指针,他们所能做的就是索引到特定的BST,但与您打算维护哈希表的功能,跟踪当前有多少个存储桶,有多少个元素的变量都没有关联。包含等。您应该将数组放入提供所有这些功能的类中。 there are lots of design decisions, but it should look something like this: 有很多设计决策,但是应该看起来像这样:

template <typename Key, typename Value>
class Hash
{
  public:
    Hash() : p_(NULL), size_(0), num_buckets_(0) { }

    // find/make entry for Key, giving read/write access to the current/a-default value
    Value& operator[](const Key&);        
    const Value& operator[](const Key&) const;

    // try to find an entry, throw an exception if not found...
    Value& at(const Key&);
    const Value& at(const Key&) const;

    // report whether a key is already in the hash table...
    bool has_key(const Key&) const;

    int size() const;

  private:
    BST* p_;
    int num_buckets_;
    int size_;
};

(yet again, I can only recommend that you first try this with p_ replaced with that vector of maps). (再次,我只能建议您先将p_替换为地图的矢量,然后尝试使用此方法)。

The second point is memcpy, which I'm not being allowed to do by the compiler. 第二点是memcpy,编译器不允许我这样做。

memcpy(prevData[x], currData[x], sizeof(BST) * height); memcpy(prevData [x],currData [x],sizeof(BST)*高度);

Complains about 投诉

error C2664: 'memcpy' : cannot convert parameter 1 from 'BST' to 'void *' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 错误C2664:'memcpy':无法将参数1从'BST'转换为'void *'没有可用的用户定义转换运算符可以执行此转换,或者无法调用该运算符

It's a very bizarre request to copy everything from one bucket in one hash table into the same bucket in another hash table. 将所有内容从一个哈希表中的一个存储桶复制到另一个哈希表中的相同存储桶是一个非常奇怪的请求。 If, for example, the number of buckets differs or the hash function differs then you'll probably corrupt the destination bucket. 例如,如果存储桶数不同或哈希函数不同,那么您可能会破坏目标存储桶。 Anyway, I suggest you implement a BST class with value semantics (ie a copy constructor and operator= that replicates an existing tree). 无论如何,我建议您使用值语义实现BST类(即,复制现有树的副本构造函数和operator =)。 Then you can simply use: 然后,您可以简单地使用:

prevData.buckets[x] = currData.buckets[x];

(note: operator should look up in the hash table, and given the key type ought to be able to be int, you don't want to use the same notation for copying entire buckets - you can't overload a function if both have the same signature. That's why here I show buckets being the exposed container of BSTs - exposing this breaks encapsulation; in real classes you just don't want users even aware of the buckets (or BSTs for that matter)). (注意:运算符应在哈希表中查找,并且键类型应为int,因此您不想使用相同的符号来复制整个存储桶-如果两个函数都具有这就是为什么我在这里将存储桶显示为BST的暴露容器的原因-暴露了这种破坏封装的情况;在真实的类中,您甚至不希望用户意识到存储桶(或相关的BST)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM