简体   繁体   English

使用std :: vector :: iterator来改变存储在std :: vector中的值?

[英]Use std::vector::iterator to alter values stored in std::vector?

I'm new to C++, and am trying to implement the Selection Sort Algorithm as an exercise. 我是C ++的新手,我正在尝试将选择排序算法作为练习来实现。

I've gotten as far as trying to swap the value in the left-most memory location with the value in the memory location of the minimum of the unsorted portion of the vector. 我已经尝试将最左边的内存位置的值与向量的未排序部分的最小内存位置中的值进行交换。

( See the code below. ) (参见下面的代码。)

Is it possible to use std::vector::iterator 's to alter the values contained in the vector it belongs to? 是否可以使用std::vector::iterator来改变它所属的向量中包含的值?

#include <vector>
#include <stdlib.h>
#include <time.h>
#include <iostream>

using namespace std;

template<typename T>
ostream& operator<<( ostream& out, vector<T> thisVector ) {

  for( size_t i = 0, choke = thisVector.size(); i < choke; i++ )
    out << thisVector[ i ] << " ";

  return out;
}

template<typename T>
typename vector<T>::iterator get_minimum( vector<T>& thisVector, typename vector<T>::iterator pos, typename vector<T>::iterator end ) {

  T min = *pos;
  typename vector<T>::iterator minPos;

  while ( pos != end ) {
    if ( *pos < min ) {
      min = *pos;
      minPos = pos;
    }
    pos++;
  }
  return minPos;
}

template<typename T>
void swap( typename vector<T>::iterator pos, typename vector<T>::iterator& minPos ) {

  T temp = *pos;

  // I was hoping the following two lines would modify the vector passed to selection_sort
  pos = *minPos;
  minPos = temp;
  return;
}

template<typename T>
void selection_sort( vector<T>& thisVector, typename vector<T>::iterator pos ) {

  typename vector<T>::iterator end = thisVector.end();
  typename vector<T>::iterator minPos = get_minimum( thisVector, pos, end );
  cout << "Swap was given this " << *pos << " " << *minPos << endl;
  swap( pos, minPos );
  cout << "and returned this " << *pos << " " << *minPos << endl;
  return;
}

int main() {

  // initialize random seed
  srand (time(NULL));

  // Create data stub
  vector<int> myThing;
  do {
    myThing.push_back( rand() % 20 );
  } while ( myThing.size() <= 10 );

  cout << "Unsorted: " << myThing << endl;
  selection_sort( myThing, myThing.begin() );
  cout << "  Sorted: " << myThing << endl;

  return 0;
}

Yes, it is possible. 对的,这是可能的。 Given an iterator iter , *iter can be assigned to like a normal lvalue to modify the underlying container, eg: 给定迭代器iter*iter可以像普通左值一样分配来修改底层容器,例如:

*iter = 5;  // The value in the container that `iter` points to is now 5.

It is possible. 有可能的。 And here is a trick to make your life easier. 这是让你的生活更轻松的一招。

Swap is already a defined function. 交换已经是一个定义的函数。

Add #include <utility> and you get swap for free. 添加#include <utility>免费获得swap Many C++ objects define swap specializations. 许多C ++对象定义交换特化。 For example, std::vector implements a swap between two vectors by simply swapping the pointers. 例如, std::vector通过简单地交换指针来实现两个向量之间的交换。

For your code you can remove your definition of swap and use swap(*pos, *minPos) 对于您的代码,您可以删除交换的定义并使用swap(*pos, *minPos)

I needed to namesapce my code: being a very new newbie, I hadn't realized std::swap(iter, iter) already exists, and was being called--rather than my swap function. 我需要将我的代码命名为:作为一个非常新的新手,我没有意识到std::swap(iter, iter)已经存在,并且被调用 - 而不是我的swap函数。

Nonetheless, once I namespaced my code, jwodder's response proved to do the trick: by using *iter rather than iter , my code compiled and the vector was properly modified by swap . 尽管如此,一旦我命名我的代码,jwodder的响应就证明了这一点:通过使用*iter而不是iter ,我的代码被编译并且向量被swap正确修改。

The problem that you are facing with swapping the values the iterators point to is caused by the fact that the compiler picks up std::swap by using ADL. 交换器指向的值所面临的问题是由编译器通过使用ADL获取std::swap这一事实引起的。 std::swap just swaps where the iterators point to but not the values the iterators point to. std::swap只是交换迭代器指向的位置,而不是迭代器指向的值。

If you name the function myswap and call myswap instead of swap , you are probably going to see compiler error messages. 如果将函数命名为myswap并调用myswap而不是swap ,则可能会看到编译器错误消息。 Check out my question on the subject . 看看我关于这个问题的问题

Instead, if you use: 相反,如果您使用:

template<typename Iterator>
void myswap(Iterator pos1,
            Iterator pos2)
{
   auto temp = *pos1;
   *pos1 = *pos2;
   *pos2 = temp;
}

everything should work. 一切都应该有效。 Here's a working program, using g++ 4.8.2. 这是一个使用g ++ 4.8.2的工作程序。

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

template<typename Iterator>
void myswap(Iterator pos1, Iterator pos2)
{
   auto temp = *pos1;
   *pos1 = *pos2;
   *pos2 = temp;
}

void testMyswap()
{
   std::cout << "\nTesting myswap()\n";
   std::vector<int> v{1, 2, 3, 4, 5, 6};

   std::vector<int>::iterator iter = v.begin();
   std::vector<int>::iterator temp = std::next(iter, 2);

   std::cout << "Values iterators point to before swap.\n";
   std::cout << *iter << " " << *temp << std::endl;
   myswap(iter, temp);
   std::cout << "Values iterators point to after swap.\n";
   std::cout << *iter << " " << *temp << std::endl;

   std::cout << "The vector after the swap.\n";
   for ( iter = v.begin(); iter != v.end(); ++iter )
   {
      std::cout << *iter << " ";
   }
   std::cout << std::endl;
}

int main()
{
   testMyswap();
   return 0;
}

Output 产量

Testing myswap()
Values iterators point to before swap.
1 3
Values iterators point to after swap.
3 1
The vector after the swap.
3 2 1 4 5 6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM