通过指针调用函数 - 访问冲突读取位置

时间:2013-05-07 14:58:25

标签: c++ pointers access-violation

我有一个返回Customer对象(不是指针)的函数,如下所示:

Customer CustomerList::retrieve(const int index) const{
        if (index<1 || index>size)
                return false;
        else{
                Node *cur = find(index);
                return (cur->data);
        }
}

此函数从Customer(链接列表)中获取CustomerList个对象。

我正在尝试使用以下函数操作列表中的Customer(此函数会向Account对象添加Customer。)

list.retrieve(i).addAccount(acc);

但是,在此函数调用之后,Customer中的CustomerList对象不会更改。我假设原因是我返回了Customer对象的副本,而不是对象本身。

因此,为了返回客户的地址并正确操作,我对我的功能进行了以下更改。

Customer* CustomerList::retrieve(const int index) const{
        if (index<1 || index>size)
                return false;
        else{
                Node *cur = find(index);
                return &(cur->data);
        }
}

然后调用操作函数:

list.retrieve(i)->addAccount(acc);

但是它给了我“访问冲突读取位置0x00000044。”错误。我想学的是:

  1. 为什么不首先操纵Customer对象?我的假设是对的吗?
  2. 在我更改函数和函数调用之后,为什么它会给我上面提到的错误?

2 个答案:

答案 0 :(得分:1)

  

为什么不首先操纵Customer对象?我的假设是对的吗?

正如你所说,你正在返回一份副本并对其进行操作,使列表中的副本保持不变。

  

在我更改函数和函数调用之后,为什么它会给我上面提到的错误?

几乎可以肯定是因为:

return false;

如果索引超出范围,那将返回空指针。如果这是您想要的行为,那么您需要在取消引用指针之前进行检查:

if (Customer * c = list.retrieve(i)) {
    c->addAccount(acc);
} else {
    // handle the error?
}

并且,出于礼貌,您应该返回看起来更像空指针的内容,例如nullptrNULL0

抛出异常(也许是std::range_error)可能是个更好的主意;然后调用者可以假设指针在函数返回时有效。在这种情况下,返回引用而不是指针也可能更好,因为代码与原始示例非常相似:

Customer & CustomerList::retrieve(const int index) const{
    if (index<1 || index>size)
            throw std::range_error("Customer index out of range");
    else{
            Node *cur = find(index);
            return (cur->data);
    }
}

list.retrieve(i).addAccount(acc); // Does exactly what you'd expect

如果看起来合适,我也可以考虑将范围检查移到find函数中。

答案 1 :(得分:0)

  
      
  1. 为什么不首先操纵Customer对象?
  2.   

是的,你是对的。通过defualt其重新调整的by value不是通过引用,因此列表中的原始对象未进行修改。

  
      
  1. 在我更改函数和函数调用之后,为什么它会给我上面提到的错误?
  2.   

我认为你需要分享addAccount方法的代码。问题可能在其中。 考虑到原始代码return by value,它正在进行核心工作(毫无例外)。