1

I want to move one vector to another without a copy. I found this STL vector: Moving all elements of a vector. I wanted to test it out so I coded up a simple example below.

C++ compiler version:

g++ 5.1.0 on (Ubuntu 5.1.0-0ubuntu11~14.04.1)

I am compiling using the following command:

g++ -std=c++14 test2.cpp -o test2

Here is the code, I have written:

#include <iostream>
#include <memory>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  vector<uint8_t> v0 = { 'h', 'e', 'l', 'l', 'o' };
  vector<uint8_t> v1 = {};

  // pointer to the data
  // portion of the vector
  uint8_t* p0 = v0.data();
  uint8_t* p1 = v1.data();

  // for stdout
  string s0(v0.begin(), v0.end());
  string s1(v1.begin(), v1.end());

  cout << "s0='" << s0 << "' addr=" << &p0 << endl;
  cout << "s1='" << s1 << "' addr=" << &p1 <<endl;

  /// here i would think the pointer to the data in v1
  /// would point to v0 and the pointer to the data in v0
  /// would be something else.
  v1 = move(v0);

  p0 = v0.data();
  p1 = v1.data();

  s0.assign(v0.begin(), v0.end());
  s1.assign(v1.begin(), v1.end());

  cout << "s0='" << s0 << "' addr=" << &p0 << endl;
  cout << "s1='" << s1 << "' addr=" << &p1 << endl;  
}

and here is the output:

s0='hello' addr=0x7fff33f1e8d0
s1='' addr=0x7fff33f1e8d8
s0='' addr=0x7fff33f1e8d0
s1='hello' addr=0x7fff33f1e8d8

If you see the output the addresses have not changed at all. I would think the address for p1 would have the address for p0 and p0 would point to something else. Does anyone know why the addresses have not changed? I guess, I'm wondering if the compiler actually implemented this with a copy as a short cut.

Community
  • 1
  • 1
bantl23
  • 879
  • 2
  • 9
  • 8

2 Answers2

4

You're printing the addresses of the pointers, not the addresses that they point to.

Print p0 and p1 rather than &p0 and &p1.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
3

You want:

cout << "s0='" << s0 << "' addr=" << (void*) p0 << endl;
cout << "s1='" << s1 << "' addr=" << (void*) p1 << endl;

instead of:

cout << "s0='" << s0 << "' addr=" << &p0 << endl;
cout << "s1='" << s1 << "' addr=" << &p1 <<endl;
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Why is the `(void*)` cast needed when combined with `cout` stream? – syntagma Sep 17 '15 at 22:11
  • @REACHUS I was experimenting with this [ideone](http://ideone.com/vr175L), and realized that `cout` identifies the pointer as a string, so it prints the contents instead of the address. – Austin Mullins Sep 17 '15 at 22:15
  • @AustinMullins then the question would be why does `cout` treat `(void *)` in a different way. BTW it gives a segfault on my machine without the cast and I know I should do the cast but don't really know why. – syntagma Sep 17 '15 at 22:17
  • The reason is that the `operator<<` function has several specialized overloads for different cases. After the `move` function call, the `data` pointers on both vectors has a type that causes `cout` to perform normal string behavior. One such behavior is a segfault when trying to print `NULL`, which is the final value of `p0`. – Austin Mullins Sep 17 '15 at 22:21
  • 3
    The reason for the `(void*)` cast is because a `uint8_t` type is generally a typedef for an `unsigned char`. `char*` types passed to an `ostream` will use an overload that will try to print the string pointed to by the pointer. Casting to a `(void*)` uses an overload that dumps the value of the pointer. – Michael Burr Sep 17 '15 at 22:25