【问题标题】:C++, assigning value to vector::end?C++,给vector::end赋值?
【发布时间】:2017-02-06 07:16:05
【问题描述】:

假设我有一个向量 v{1, 2, 3, 4, 5}。我想削减最后两个元素,所以我想我会做类似的事情

v.end() = v.begin() + 3;

让我们来看看这个sn-p:

std::vector<int> v {1,2,3,4,5};
std::cout << *(v.end()-1) << std::endl;
v.end() = v.begin() + 3;
std::cout << *(v.end()-1) << std::endl;

这两种情况下都会打印 5。这是为什么?如果 vector::end 返回一个迭代器,它不是一个右值吗?如果是这样,代码根本不应该编译。如果是左值,为什么结束迭代器不指向元素v.begin() + 3?

【问题讨论】:

  • 如果你想知道你是否可以赋值给一个右值,你应该使用一个不太容易混淆的例子。如果您想知道如何从向量中“剪切最后两个元素”,那么也许您可以删除右值的东西。这两个问题相互干扰,使问题变得不清楚。
  • 好的,我会记住这一点的,谢谢
  • @juanchopanza:这句话并不完全公平。您必须假设有问题的人对问题没有完全理解,这毕竟是他们问的原因。如果您处于编写上述代码的 C++ 级别,那么期望您了解有关左值和右值的细节是不合理的。所以你可能会看到它失败了,然后开始推理会发生什么,最后得到上面的问题。考虑到它是真正的可编译代码,具有预期和实际结果,我会说它适合 StackOverflow。

标签: c++ vector iterator


【解决方案1】:

std::end() 返回一个迭代器,它指向最后一个元素之后的元素。它只能用作参考(例如,将另一个迭代器与它进行比较),尝试使用它的值是未定义的行为。

话虽如此,这段代码v.end() = v.begin() + 3; 只是重新定位从向量中获得的迭代器的副本,它不会修改向量本身。

考虑使用erase 重载之一来截断向量的一部分。

【讨论】:

    【解决方案2】:

    每次调用v.end(),都会返回一个新的迭代器对象。这是一个右值,但您仍然可以更改它的值,但这对容器没有任何影响,您的 v。 如果您想从向量中删除某些内容,请使用例如vector::erase().

    【讨论】:

    • 我认为你的意思是它是一个右值。
    • 嗯,不是吗?它是一个对象(类型迭代器),它占用内存,你可以给它赋值 --> 它是一个左值。
    • 它是一个右值。 v.end() 是一个右值表达式(您可以通过编写几个函数轻松检查,void foo(const vector&lt;int&gt;::iterator&amp;); 和 void foo(vector&lt;int&gt;::iterator&amp;&amp;) 并查看哪个重载结果拾取。)
    • 我猜 R 或 L 值对于 C++ 来说太简单了。 Xvalue 呢?
    • 好的,改成右值了。
    【解决方案3】:

    您不能像需要擦除的那样分配结束迭代器。

    v.erase(v.begin() + 3, v.end());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-09
      • 2015-10-10
      • 2017-08-20
      • 2013-07-13
      • 2018-05-28
      • 2020-10-02
      • 1970-01-01
      • 2017-02-17
      相关资源
      最近更新 更多