使用重载的下标运算符分配值

时间:2012-01-31 00:24:39

标签: c++ operators overloading subscript

我正在尝试使用下标运算符创建从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

with backtrace

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

6 个答案:

答案 0 :(得分:1)

起初......这个:

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

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

第二件事是你试图将CEntry *分配给CEntry,如果你有CEntry *operator=( CEntry *orig)这会有用,但我认为这是不好的编码习惯。

答案 1 :(得分:0)

由于EntriesArray::operator[]会返回CEntry &,但new CEntry会返回CEntry *

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


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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

您可以尝试替换

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()来删除它们。

答案 4 :(得分:0)

继上面的评论: 为了使它能够编写新值,您可能需要这样的东西 (我没有通过一个或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];
};

答案 5 :(得分:0)

此问题可能与this one有关。

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

  

(在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; }

我希望它有所帮助。