2012-01-06 24 views
3

我從我的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 
} 

任何想法?

+11

請提供編譯和演示該問題最小的情況下。 – 2012-01-06 18:01:22

+1

除非「某個位置」超出了字符串的長度(即等於或過去:: end()),否則這種情況可能不會發生。 – 2012-01-06 18:03:34

回答

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:我擺脫auto 11 C++的,因爲我沒有在時刻兼容的編譯器)

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 const字符串成員函數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()的地址是不同的。

+1

請注意,即使簽名使用'const std :: string&',如果該函數被稱爲return_iterator(「foo」)或類似的構造臨時字符串並將常量引用傳遞給暫時的。我猜這就是OP的實際代碼中發生的事情。 – 2012-01-06 18:16:12

+0

@AndréCaron:對。這可能是問題所在。 – 2012-01-06 18:20:48