【问题标题】:return reference of an object from an iterator从迭代器返回对象的引用
【发布时间】:2012-05-11 10:55:02
【问题描述】:

我想从向量中返回一个对象的引用,并且该对象在一个迭代器对象中。我该怎么做?

我尝试了以下方法:

Customer& CustomerDB::getCustomerById (const string& id) {
    vector<Customer>::iterator i;
    for (i = customerList.begin(); i != customerList.end() && !(i->getId() == id); ++i);

    if (i != customerList.end())
        return *i; // is this correct?
    else
        return 0; // getting error here, cant return 0 as reference they say
}

代码中customerList是一个客户向量,getId函数返回客户的id。

*i 正确吗?以及如何返回 0 或 null 作为参考?

【问题讨论】:

    标签: c++ reference vector null iterator


    【解决方案1】:

    return *i; 是正确的,但是您不能返回 0 或任何其他此类值。如果在向量中找不到客户,请考虑抛出异常。

    返回对向量中元素的引用时也要小心。如果 vector 需要重新分配其内存并移动内容,则在 vector 中插入新元素会使您的引用无效。

    【讨论】:

    • 另外,他可以返回一个指针。类似于return i != customerList.end() ? &amp;*i : NULL;
    • 几乎可以通过一些不确定的转换来创建一个空引用,但这是一个真的坏主意,而且很可能在几乎所有可能的情况下都是 UB。
    • 是的,这在很大程度上取决于函数的预期用途。如果调用函数时最初的期望是客户应该存在,那么抛出异常是有意义的。如果它的目的更多是询问“客户是否存在,如果存在,则返回客户”,那么返回可为空的类型更有意义。
    • 如果您知道向量将包含的最大元素数,您可以使用向量的reserve() 函数预先保留容量。那么只要向量的大小不超过容量,插入新元素时元素就不会移动。如果您事先不知道容量,请考虑使用另一种容器。例如std::deque 的行为类似于vector,但在需要调整大小时不会重新分配其所有内存;它只会为新元素分配一个新块(因此内存是部分分段的)。
    • 另外请记住,插入新元素并不是使向量引用无效的唯一方法,如果删除向量中间的元素,它会将之后的元素向下移动,因此无效对它们的引用/迭代器。如果您曾经做过类似的事情,那么使用std::list 之类的容器可能更适合您。最后,保证您的引用/迭代器不会失效的一种方法就是不要将引用保存在内存中足够长的时间以插入新元素。
    【解决方案2】:

    没有“空”引用之类的东西:如果您的方法获得的 id 不在向量中,它将无法返回任何有意义的值。正如@reko_t 指出的那样,当向量重新分配其内部时,即使是有效的引用也可能变得无效。

    仅当您始终可以返回对将在一段时间内保持有效的现有对象的引用时,才应使用引用返回类型。在你的情况下,两者都不能保证。

    【讨论】:

    • +1 用于提及有效性问题(无论函数返回引用、指针还是迭代器都有效)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 2017-03-20
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    相关资源
    最近更新 更多