我尝试使用以下代码概括流对象:
#include <iostream>
#include <vector>
#include <sstream>
#include <iterator>
using namespace std;
template<class T, class U>
T& operator<<(T& os, vector<U> vec)
{
vector<string>::iterator begin = vec.begin();
vector<string>::iterator end = vec.end();
for (; begin != end; ++begin)
os << *begin << " ";
return os;
}
int main()
{
vector<string> things({
"car", "truck", "rabbit"
});
ostringstream oss;
oss << things << endl;
copy(oss.str().begin(), oss.str().end(), ostream_iterator<char>(cout, ""));
}
现在它适用于cout << things
和string str = oss.str(); copy(str.begin() ...
,但不适用于oss.str().begin()
。据我所知,str()
返回一个字符串对象,其中包含当前流内容的副本。那么为什么我们需要将它复制两次,一次是从str()
复制一次,一次是在字符串对象的初始化中复制一次?此问题与使用c_str()
不同。
以下也有效:
string::iterator begin = oss.str().begin();
string::iterator end = oss.str().end();
copy(begin, end, ostream_iterator<char>(cout, ""));
答案 0 :(得分:7)
据我所知,str()返回一个带有副本的字符串对象 流的当前内容。
这是正确的。这是你的问题的答案。因为str()
返回一个副本,所以对oss.str()
的两次调用会产生两个完全不同的副本(即两个不同的字符串对象)。两个相应字符串对象的迭代器不兼容,因为它们不是来自同一个字符串。将两个完全不同的字符串中的两个迭代器传递给一个算法(例如std::copy
)是不确定的行为,它希望它们来自相同的范围。
你不会指望这个有用吗,对吗?
std::string str1 = oss.str();
std::string str2 = oss.str();
std::copy(str1.begin(), str2.end(), ostream_iterator<char>(cout, ""));
为了回应您的编辑,“以下也有效:”。如果这样可行,那纯粹是巧合。这些迭代器在创建它们的语句的末尾都是无效的,因为它们指向的字符串不再存在。您在std::copy
调用中对它们的使用是未定义的行为。