分配给std :: vector <t> :: begin()的结果是什么?

时间:2019-03-29 19:29:51

标签: c++ vector

我对左值和右值有一些了解。因此,据我所知,我们不能分配给右值,但是非常量左值是可以的。

#include <iostream>
#include <vector>
int main(){

    std::vector<int> v{ 1, 2, 3, 4, 5 };
    v.begin() = v.end() - 2;
    std::cout << *v.begin() << std::endl; // 1
    for (auto const& e : v)
        std::cout << e << ", ";// 1, 2, 3, 4, 5,
    std::cout << std::endl;
}

为什么我可以分配给begin()却对元素没有任何作用?

3 个答案:

答案 0 :(得分:17)

v.begin()是一个迭代器。分配给迭代器不会分配给迭代器指向的值。此外,由于v.begin()是一个prvalue,因此分配给您的对象在行的末尾被销毁,而不会影响v或它拥有的任何“永久”内存。

如果v.begin()是原始指针,则编译器将在尝试分配给右值时发出错误。但是,类型std::vector<T>::iterator通常是类类型,在您的实现中似乎是这种情况(带有正在使用的特定编译器标志集),因此分配给v.begin()会调用{该类类型的{1}}。但这并不能改变以下事实:迭代器对象是一个临时对象,对其进行分配不会产生进一步的影响。

为了分配给operator=所指向的元素,您需要取消引用:v.begin()

答案 1 :(得分:6)

  

分配给std :: vector :: begin()的结果是什么?

赋值表达式的结果(在您的示例中结果被舍弃)是赋值。在这种情况下,结果与v.end() - 2相同。

请注意,由于begin()返回一个值,因此此分配仅修改返回的临时对象。分配不会以任何方式修改向量。考虑到临时对象被丢弃,该分配在实践中没有可观察到的效果。

此外,如果标准库选择将std::vector::iterator实现为指针,则此赋值可能格式错误。

  

为什么我可以分配给begin()

因为

  1. 迭代器是可分配的。
  2. 可以为分配类类型的右值。
  3. 迭代器恰好是类类型。
  

但是它对元素没有任何作用吗?

因为分配迭代器不会修改迭代器指向的元素。相反,分配会更改迭代器指向的对象。

  

据我所知,我们无法分配给右值

这通常是不正确的。尤其是对于类类型而言并非如此。


除非该类的赋值运算符具有lvalue-ref-qualifier(并且没有rvalue-ref限定的重载),否则这是非常规的。

答案 2 :(得分:3)

有时代码比单词更能说明问题。您的代码与此等效:

std::vector<int> v{ 1, 2, 3, 4, 5 };

{
    auto temp = v.begin();
    temp = v.end() - 2;
}

std::cout << *v.begin() << std::endl; // 1
for (auto const& e : v)
    std::cout << e << ", ";// 1, 2, 3, 4, 5,
std::cout << std::endl;

换句话说,v.begin() = v.end() - 2没有明显的作用。这只是对临时工的分配。