返回迭代器似乎使它无效

时间:2012-01-06 17:54:49

标签: c++ iterator

我在使用它之后从我的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
}

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

由于您发布的示例代码未编译(typename std::string::const_iterator应该只是std::string::const_iterator),修复此错误允许代码run as expected,我猜测实际的代码有点不同。

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

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

按值传递字符串。由于COW,副本是共享的,但是当函数调用line.begin()时,非const 字符串成员函数std::string::begin()被调用,这意味着该副本的新副本通常会创建基础字符串。然后,返回的非const 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()的地址不同。

答案 1 :(得分:0)

我假设,实际代码可能有模板(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);
}

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

(PS:我摆脱了C ++ 11的auto,因为我目前没有兼容的编译器)