I have the following task: you need to rewrite some of the elements of one container to another (in the example, everything is rewritten, but this is an example). In the example, for simplicity, int, but in my code there are quite voluminous objects, and, of course, I would like to write pointers to the receiver container, rather than rewrite the contents (the original container will not change while the receiver container is in operation, so the pointers will workers).

#include <iostream> #include <vector> class Test { public: std::vector<int> testvector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; std::vector<int*> ptrvector; void testmethod() { for(auto i:testvector) ptrvector.push_back(&i); for(auto i:ptrvector) std::cout << *i << std::endl; } }; int main() { Test test; test.testmethod(); return 0; } 

This code will print zeros instead of the entire number series. This line is of course erroneous ptrvector.push_back (& ​​i), because Here the address of the iterator is written, and not the object from the vector.

How do i get a pointer through iterator i?

  • And what prevents to keep iterators in another container, if you guarantee their validity? Syntactically, the iterator is no different from the pointer. - VladD
  • 2
    And &i is not the address of the iterator, but the address of a temporary variable to which the array element is copied. - VladD

3 answers 3

First option:

 void testmethod() { for(auto & i : testvector) // берем не копию, а ссылку на элемент ptrvector.push_back(&i); for(auto i:ptrvector) std::cout << *i << std::endl; } 

The second option, using the data function:

 void testmethod() { for(size_t i = 0; i < testvector.size(); ++i) ptrvector.push_back(testvector.data() + i); for(auto i:ptrvector) std::cout << *i << std::endl; } 
  • The first option is just what I need, thank you. - user206565

Once you are given iterators, you need to use iterators.

 vector<int> testvector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; vector<vector<int>::iterator> ptrvector; for (auto iter = begin(testvector); iter != end(testvector); ++iter) ptrvector.push_back(iter); for (auto iter : ptrvector) cout << *iter << " "; 

Check: http://ideone.com/s9CGDN


But this code is quite fragile. Changing the starting container invalidates iterators. (However, it would also invalidate pointers.)


Here's a sample code that works with [almost] any type of container.

 template<typename Container> auto get_pointers(const Container& c) { vector<decltype(begin(c))> ptrvector; for (auto iter = begin(c); iter != end(c); ++iter) ptrvector.push_back(iter); return ptrvector; } 

With this you can write like this:

 vector<int> testvector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; auto ptrs1 = get_pointers(testvector); for (auto p : ptrs1) cout << *p << " "; int testarray[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 }; auto ptrs2 = get_pointers(testarray); for (auto p : ptrs2) cout << *p << " "; unordered_set<int> testset = { 21, 22, 23, 24, 25, 26, 27, 28, 29, 20 }; auto ptrs3 = get_pointers(testset); for (auto p : ptrs3) cout << *p << " "; 

Check: http://ideone.com/wHxZtM

    Standard tasks should be solved by standard algorithms. To copy from one container to another, you would use std::copy / std::copy_if . But since the types of elements stored in containers cannot be implicitly and correctly transformed into each other, the std::transform function will be suitable:

     #include <algorithm> #include <iostream> #include <iterator> #include <vector> int main() { std::vector<int> testvector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; std::vector<int*> ptrvector; std::transform(testvector.begin(), testvector.end(), std::back_inserter(ptrvector), [](int& el) { return &el; }); for(const int* p: ptrvector) { std::cout << *p << " "; } std::cout << "\n"; } 

    The result of the execution.