C++中能否将std::getline与std::vector<std::string>结合以省去临时存储变量
原有实现的潜在问题说明
你给出的两段原始代码都存在逻辑瑕疵:while(file.good()) 是在读操作前判断流状态,就算最后一次std::getline 因为读到EOF/读取失败返回错误状态,你还是会把无效的空字符串存入vector,导致结果多一个冗余元素。正确的逻辑应该把std::getline放到循环条件中,直接判断读操作是否成功。
方案1:C++14即可用,无额外依赖的极简循环写法
不需要单独声明临时line变量,也不需要额外写push_back调用,直接利用emplace_back返回的引用操作:
while (true) { // 直接在vector尾部构造空字符串,拿到可写引用 auto& current_line = vec.emplace_back(); if (!std::getline(file, current_line)) { // 读取失败,弹出刚构造的空字符串,退出循环 vec.pop_back(); break; } }
这个写法完全符合C++14标准要求,没有额外拷贝开销,逻辑也完全正确。
方案2:C++14即可用,自定义行迭代器实现无显式循环
你可以自定义一个输入迭代器封装逐行读取的逻辑,直接用来初始化vector,完全不需要写循环代码:
#include <iterator> #include <string> #include <istream> class LineInputIterator { std::istream* stream_ = nullptr; std::string line_; public: using iterator_category = std::input_iterator_tag; using value_type = std::string; using difference_type = std::ptrdiff_t; using pointer = const std::string*; using reference = const std::string&; LineInputIterator() = default; explicit LineInputIterator(std::istream& is) : stream_(&is) { ++*this; } reference operator*() const { return line_; } pointer operator->() const { return &line_; } LineInputIterator& operator++() { if (stream_ && !std::getline(*stream_, line_)) { stream_ = nullptr; } return *this; } LineInputIterator operator++(int) { auto tmp = *this; ++*this; return tmp; } bool operator==(const LineInputIterator& other) const { return stream_ == other.stream_; } bool operator!=(const LineInputIterator& other) const { return !(*this == other); } };
使用时直接一行初始化vector即可:
std::vector<std::string> vec(LineInputIterator(file), LineInputIterator());
方案3:C++23标准下的最简写法
C++23引入了范围库的std::views::getlines和std::ranges::to,可以一行完成所有操作,完全不需要任何临时变量和显式循环:
#include <ranges> #include <vector> auto vec = std::views::getlines(file) | std::ranges::to<std::vector>();
内容的提问来源于stack exchange,提问作者user2138149
相关产品推荐
相关产品推荐

