使用重载的下标运算符赋值

Assign value using overloaded subscript operator

本文关键字:运算符 赋值 下标 重载      更新时间:2023-10-16

我正在尝试使用下标运算符创建从1索引的自定义数组。获取值很好,但我不知道为什么使用下标运算符赋值不起作用。

class CEntry {
public:
  CKey key;
  CValue val;
  CEntry(const CKey& key, const CValue& val) {
    this->key = key;
    this->val = val;
  }
  CEntry& operator= (const CEntry& b) {
    *this = b;
    return *this;
  };
};

class EntriesArray {    
public:
    CEntry **entries;
    int length;
  EntriesArray(int length) {
    this->length = length;
    entries = new CEntry*[length];
    int i;
    for (i = 0; i < length + 1; i++) {
        entries[i] = NULL;
    }
  };
  CEntry& operator[] (const int index) {
      if (index < 1 || index > length) {
          throw ArrayOutOfBounds();
      }
      return *entries[index - 1];
  };
};

以这种方式构建阵列

EntriesArray a(5);

这适用于

 a.entries[0] = new CEntry(CKey(1), CValue(1));
 cout << a[1].val.value << endl;

不起作用

a[1] = new CEntry(CKey(1), CValue(1));

编辑:

使用

CEntry *operator=( CEntry *orig)

它编译okey,但gdb在停止

No memory available to program now: unsafe to call malloc warning: Unable to restore previously selected frame

带有回溯

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5f3ffff8
0x00000001000013c8 in CEntry::operator= (this=0x0, orig=0x1001008d0) at /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp:20
20  /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp: No such file or directory.
in /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp

起初。。。此:

CEntry& operator= (const CEntry& b) {
    *this = b;
    return *this;
};

不应该工作(这将导致operator=的递归调用)。

第二件事是,您正在尝试将CEntry *分配给CEntry,如果您有CEntry *operator=( CEntry *orig),这会起作用,但我认为这是一种糟糕的编码实践。

这个问题可能与这个问题有关。

我试图修复你的代码;我相信这就是你想要做的:

(在g++5.3.0上测试了该代码)

#include <iostream>
#include <stdexcept>
#include <string>
// Some implementation for CKey and CValue:
typedef int CKey;
struct CValue {
  int value;
  CValue(int value=0) : value(value) {}
};
class CEntry {
public:
  CKey key;
  CValue val;
  CEntry(): key(0), val(0) {}
  CEntry(const CKey& key, const CValue& val): key(key), val(val) {}
  CEntry& operator= (const CEntry& b) {
    this->key = b.key;
    this->val = b.val;
    return *this;
  };
};
class EntriesArray {    
public:
    CEntry *entries;
    int length;
  EntriesArray(int length) {
    this->length = length;
    entries = new CEntry[length];
  };
  CEntry& operator[] (const int index) {
      if (index < 1 || index > length) {
          throw std::domain_error("out of bounds!");
      }
      return entries[index - 1];
  };
};
int main(int argc, char* argv[]) {
  using namespace std;
  EntriesArray a(5);
  // This works
  a.entries[0] = CEntry(CKey(1), CValue(1));
  cout << a[1].val.value << endl;
  // This doesn't work
  a[1] = CEntry(CKey(2), CValue(2));
  cout << a[1].val.value << endl;
}

此外,您可能希望使用a[1]作为a[1].val.value,例如:

cout << a[1] << endl;

要做到这一点,只需将此行添加到cEntry:

operator int() { return val.value; }

我希望它能有所帮助。

您可以尝试替换

CEntry& operator[] (const int index) {
    if (index < 1 || index > length) {
        throw ArrayOutOfBounds();
    }
    return *entries[index - 1];
};

带有

void Add(const int index, CEntry *pEntry) {
    if (index < 1 || index > length) {
        throw ArrayOutOfBounds();
    }
    entries[index - 1] = pEntry;
};

但是,由于您现在正在存储对堆上分配的对象的引用(使用new),您将需要一个析构函数~EntriesArray()来将它们全部删除。

因为EntriesArray::operator[]返回CEntry &,但new CEntry返回CEntry *

也许你想要a[1] = CEntry(CKey(1), CValue(1))?(无new。)


顺便说一句,您当前对CEntry::operator=的定义将导致堆栈溢出

return *entries[index - 1];

取消引用NULL指针。

您希望指针本身被a[1] = new CEntry(CKey(1), CValue(1));覆盖,而不是被指向的值覆盖。

试试这个:

class EntriesArray
{    
public:
  int length;
  CEntry **entries;
  EntriesArray( int length ) : length(length), entries(new CEntry*[length]())
  {
  }
  // defaulted special member functions are inappropriate for this class
  EntriesArray( const EntriesArray& );          // need custom copy-constructor
 ~EntriesArray();                               // need custom destructor
  EntriesArray& operator=(const EntriesArray&); // need custom assignment-operator
  CEntry*& operator[] (const int index) {
      if (index < 1 || index > length) {
          throw ArrayOutOfBounds();
      }
      return entries[index - 1];
  }
};

根据我上面的评论:为了让它与编写新的价值观相结合,你可能需要这样的东西(我还没有仔细检查过一个或ptr与参考资料的偏差)

CEntry& operator[] (const int index) {
  if (index < 1) {
      throw ArrayOutOfBounds();
  }
  // Add default elements between the current end of the list and the
  // non existent entry we just selected.
  //
  for(int i = length; i < index; i++)
  {
      // BUG is here.
      // We don't actually know how "entries" was allocated, so we can't
      // assume we can just add to it.
      // We'd need to try to resize entries before coming into this loop.
      // (anyone remember realloc()? ;-)
      entries[i] = new CEntry();
  }
  return *entries[index - 1];
};