【问题标题】:Why `std::istream_iterator` has not a rvalue constructor?为什么`std::istream_iterator`没有右值构造函数?
【发布时间】:2017-03-13 09:32:21
【问题描述】:

std::istream_iterator 无法接收流作为右值的具体原因有哪些?

为了传递一个临时对象,我必须创建一个类似的函数:

template<class T, class ostream_t>
std::istream_iterator<T> my_it(ostream_t&& ostream)
{ return {ostream}; }

template<class T>
std::istream_iterator<T> my_it() { return {}; }

int main()
{
    std::string file("3.45 1.23 7,56");

    std::copy(my_it<double>(std::istringstream(file)), my_it<double>(),
              std::ostream_iterator<double>(std::cout, " "));
}

不过,这样会更方便,也更短:

int main()
{
    std::string file("3.45 1.23 7,56");

    using my_it = std::istream_iterator<double>;

    std::copy(my_it(std::istringstream(file)), my_it(),
              std::ostream_iterator<double>(std::cout, " "));
}

为什么,在三个标准更新(C++11、C++14 和 C++17)之后,这种迭代器没有右值构造函数,而几乎所有其他类型都有它?

您可以争辩说,由于迭代器是可复制的并且拥有一个引用,如果被引用的对象不再存在(std::reference_wrapper 也禁用了右值构造),您可能会得到未定义的行为,但这也可能发生在左值引用。

毕竟这是用户的土地责任。

【问题讨论】:

  • 为什么在这里使用单数 ostream 迭代器,而不是 istringstream 迭代器?您还可以在没有参数的情况下调用 my_it。您的示例似乎无效。不过,我理解潜在的问题。
  • stackoverflow.com/q/17246720/560648stackoverflow.com/q/37546443/560648 是关于此的问题,但答案没有说明为什么。真的,你应该在相关委员会的邮件列表中询问。 m.reddit.com/r/cpp/comments/3109yn/… 更接近并给出了一些想法。在istream_iterator rvalue,FWIW 的 Google 结果的第一页上。
  • @LightnessRacesinOrbit 我忘记了double 显式模板参数到ostream_iterator。不带参数的 my_it 调用创建了一个 end 迭代器。
  • @Peregring-lk 好吧,我做了一个simple test,至少在我尝试过的所有编译器上都可以,所以至少是这样。
  • @NathanOliver 不是吗?它通过引用而不是价值来获取它。引用的析构函数是无操作的。

标签: c++ c++11 iterator rvalue-reference


【解决方案1】:

我想你的答案是page 74 of Modern C++:

例如,一个 istream 对象表示一个输入值流,其中一些可能已经被读取,而其中一些可能稍后会被读取。如果要复制 istream,是否需要复制所有已读取的值以及将来要读取的所有值?处理此类问题的最简单方法是将它们定义为不存在。禁止复制流就是这样做的。

== 编辑 ==

哦,我完全误解了你的问题!我现在明白你对临时值的意思了。让我粘贴您的程序的两个版本,以突出问题。

这不会编译:

#include <string>
#include <iostream>
#include <iterator>
#include <sstream>
#include <algorithm>

int main()
{
    std::string file("3.45 1.23 7,56");

    using my_it = std::istream_iterator<double>;

    std::copy(my_it(std::istringstream(file)), my_it(),
            std::ostream_iterator<double>(std::cout, " "));
}

但这确实:

#include <string>
#include <iostream>
#include <iterator>
#include <sstream>
#include <algorithm>

int main()
{
    std::string file("3.45 1.23 7,56");

    using my_it = std::istream_iterator<double>;

    std::istringstream a(file);
    std::copy(my_it(a), my_it(), std::ostream_iterator<double>(std::cout, " "));
}

【讨论】:

  • 我不是在谈论复制流,而是关于持有对作为右值引用传递的对象的引用(迭代器已经这样做)(因此,对临时对象)。
猜你喜欢
  • 2019-02-27
  • 2016-06-28
  • 2015-12-20
  • 2022-01-03
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
相关资源
最近更新 更多