通过指针访问调用函数违反了读取位置

calling a function through a pointer - access violation reading location

本文关键字:读取 位置 函数 指针 访问 调用      更新时间:2023-10-16

我有一个函数,返回一个Customer对象(不是指针),像这样:

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

这个函数从一个CustomerList(这是一个链表)中获得一个Customer对象。

我试图用以下函数操纵列表中的Customer(此函数将Account添加到Customer对象。)

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

但是在这个函数调用之后,CustomerList中的Customer对象没有改变。我假设原因是我返回了一个Customer对象的副本,而不是对象本身。

因此,为了返回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. 在我改变我的函数和函数调用后,为什么它给了我上面提到的错误?

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

就像你说的,你返回了一个副本,并对它进行了操作,而列表中的那个没有被修改。

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

几乎肯定是因为这个:

return false;

如果索引越界,将返回空指针。如果这是您想要的行为,那么您需要在解引用指针之前进行检查:

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

,出于礼貌,您应该返回看起来更像空指针的东西,如nullptr, NULL0

抛出一个异常(可能是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. 为什么不首先操作Customer对象?

是的,你是对的。默认情况下,它返回的by value不是通过引用,所以List中的原始对象不会被修改。

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

我认为你需要分享addAccount Method的代码。问题可能就在里面。考虑到原始代码return by value,它工作正常(没有例外)。