返回迭代器似乎会使其无效

Returning iterator seems to invalidate it

本文关键字:无效 迭代器 返回      更新时间:2023-10-16

我在使用我的fnc之后从它返回迭代器,这个迭代器在返回点指向某个字符,但在这个fnc返回它之后,返回的迭代器不再指向那个字符。我做错了什么?

typename std::string::const_iterator return_iterator(const std::string& line)
{
    auto beg = line.begin();  
/*here I'm moving this iterator and assing to it i.e.*/  
    beg = line.begin() + some_position;
    return beg;//at this point it points to a character
}  
void other_fnc(const std::string& line)
{
auto pos = return_iterator(line);//after this fnc returns pos points to some rubbish
}

有什么想法吗?

由于您发布的示例代码没有编译(typename std::string::const_iterator应该只是std::string::const_iterator),并且修复此错误可以使代码按预期运行,我猜实际代码有点不同。

在我看来,这听起来像是std::string参数按值复制的情况,并且在访问const_iterator之前,引用计数以某种方式中断。例如,此签名:

std::string::const_iterator return_iterator(std::string line)
                                                   // ^ Notice: Not passing by
                                                   //           reference

按值传递字符串。由于COW,副本是共享的,但在函数调用line.begin()的那一刻,就会调用非常数字符串成员函数std::string::begin(),这意味着通常会创建底层字符串的新副本。然后将返回的非常数iterator隐式转换为const_iterator(完全有效的转换)。

编辑:为了证明我的观点,请查看以下版本的输出,该版本被修改为按值将line参数传递给return_iterator()

#include <cassert>
#include <string>
#include <iostream>
std::string::const_iterator return_iterator(std::string line)
{
    std::string::const_iterator beg = line.begin();
    std::cout << "In return_iterator(), &(*line.begin()) is " << static_cast<const void *>(&*beg) << 'n';
/*here I'm moving this iterator and assing to it i.e.*/
    beg = line.begin() + 3;
    return beg;//at this point it points to a character
}
void other_fnc(const std::string& line)
{
    std::string::const_iterator pos = return_iterator(line);//after this fnc returns pos points to some rubbish
    std::cout << "In other_fnc(), &(*line.begin()) is " << static_cast<const void *>(&*line.begin()) << 'n';
    assert(*pos == line[3]);
}
int main()
{
    std::string line = "This is a test.";
    other_fnc(line);
}

http://codepad.org/K9yaWqWA

断言现在失败了。另外,请注意*line.begin()的地址是不同的。

我认为,实际的代码可能有模板(typename碎片),并且可能在返回类型的函数参数中没有正确引用它们。

以下代码按预期工作:

const int some_position = 2; 
template <typename T>
typename T::const_iterator return_iterator(const T& line)
{
     typename T::const_iterator beg = line.begin(); 
     beg = line.begin() + some_position;
     return beg;//at this point it points to a character
}  
void other_fnc(const std::string& line)
{
    std::string::const_iterator pos = return_iterator(line);
    std::cout << "character to 2: " << *pos << std::endl;
}
int main()
{
    std::string str = "Hello world";
    other_fnc(str);
}

根据它验证你的代码。如果你正在做其他事情,请更新你的问题。

(附言:我去掉了C++11的auto,因为我现在没有兼容的编译器)