You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用istream_iterator填充vector避免拷贝及views::istream编译报错问题

两个C++流迭代器相关问题

问题1:消除istream_iterator读取含vector成员对象时的不必要拷贝

我发现这个问题和其他类似问题存在关键差异——我见过的相关帖子都会将迭代器元素拷贝至vector。我采用file->ifstream->istream_iterator->vector的常规写法(该方式会对vector的元素类型调用>>运算符),但根据cppreference文档,istream_iterator的解引用操作仅返回最近读取对象的拷贝。

我要读取的对象包含vector成员,这意味着当前读取的对象会被拷贝至vector中(需拷贝构造整个vector成员),而读取下一个对象时又会重新构造新对象,该拷贝完全多余且会拖慢程序性能。我想知道是否有办法消除此不必要的拷贝(我设想istream_iterator可以直接move对象,或者有其他方式避免拷贝)。

示例代码如下:

#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>

struct My_class {
  std::vector<std::string> vec;

  // 用于展示构造函数调用情况的默认/拷贝/移动构造函数
  My_class() : vec{} {
      std::cout << " default" << std::endl;
  }
  My_class(My_class const &other) : vec{other.vec} {
      std::cout << " copy" << std::endl;
  }
  My_class(My_class &&other) noexcept : vec{std::move(other.vec)} {
      std::cout << " move" << std::endl;
  }


  friend std::istream& operator>>(std::istream& is, My_class& i) {
    i.vec.clear(); // 因i仍保留前一个读取对象的数据,需清空
    std::string l;
    // 其他用例中可能读取更多行,或对行预处理(如拆分)后插入vector
    std::getline(is, l);
    i.vec.push_back(l);
    return is;
  }
};

int main(int argc, char* argv[]) {
  std::ifstream ifs{argv[1]};
  std::vector<My_class> data{std::istream_iterator<My_class>{ifs}, {}};

  for(const auto& _ele : data){
      for(const auto& ele : _ele.vec){
          std::cout << ele << " ";
      }
      std::cout << std::endl;
  }
}

问题2:std::views::istream在Clang下编译报错

第二次尝试的代码:

#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
#include <memory>
#include <ranges>

static int cpy_cnt = 0;

struct My_class {
    std::vector<std::string> vec;

  // 默认构造函数
  My_class() : vec{} {
    std::cout << vec.size() << " default" << std::endl;
  }

  My_class(My_class&&)      = default;
  My_class(const My_class&) = default;

  My_class& operator=(My_class&&) = default;
  My_class& operator=(My_class&)  = default;

  friend std::istream& operator>>(std::istream& is, My_class& i) {
    i.vec.clear();
    std::string l;
    std::getline(is, l);
    i.vec.push_back(l);
    return is;
  }
};

int main(int argc, char* argv[]) {
  std::ifstream ifs{argv[1]};
  std::cout << "iter create" << std::endl;
  auto tmp = std::views::istream<My_class>(ifs);
  std::cout << "vec create" << std::endl;
  std::vector<My_class> data2{};
}

这段代码在Clang下编译报错,错误信息包含error: no matching function for call to '__begin'(此处未粘贴完整长错误信息)。经GCC和Clang反复测试,该错误仅出现在Clang中,GCC可正常编译。

编译配置命令

  • Clang编译命令:
cd build && cmake -DCMAKE_BUILD_TYPE=Debug -D CMAKE_C_COMPILER=clang -D CMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
  • GCC编译命令:
cd build && cmake -DCMAKE_BUILD_TYPE=Debug -D CMAKE_C_COMPILER=gcc -D CMAKE_CXX_COMPILER=g++ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..

编译器版本

$ g++ --version
g++ (GCC) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang++ --version
clang version 14.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix

内容的提问来源于stack exchange,提问作者atticus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 16:10:41