std::vector push_back

Hey guys I am quite confused as to why this is happening


so I looked up the arguments for std::vector.push_back() and it accepts a const reference of any type,

but when I change the original type lets say I change a string to "blah" from "hey" shouldn't this change also happen in the vector,since vector is holding a reference to the string h and not a copy?

or does the const keyword change this? and how?

thanks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

int main()
{

   string h = "hey";
   vector<string> vec;
   vec.push_back(h);
   h = "blah";

   for(int i = 0; i < vec.size(); i++){

      cout << vec[i] << endl;

   }

}
but when I change the original type lets say I change a string to "blah" from "hey" shouldn't this change also happen in the vector,since vector is holding a reference to the string h and not a copy?
You pass in a const reference, and that is copied into the container.

A const reference is used because you can have a vector to any type. That type may be large, and a const reference is passed to avoid copying the object onto the stack.
If push_back didn't take a reference as argument the object would have to be copied twice. Once when the argument is passed to function and once again when the function copies the object to the internal array. The first copy is avoided when the argument is passed by reference.
Last edited on
thanks guys :) that makes sense
quick follow up guys,

I am implementing my own vector,I am following a long with Bjarnes tutorial from practices and principles

The implementation works just like the std::vector when I change sample[0] the original h hey objects data does not get changes

but I can't see where the copy takes place in my vectors code?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

#include <iostream>

using namespace std;

template <class T,class A = allocator<T> > class Vector{

  A alloc;
  int size;
  int space;
  T *elem;

  public:
      Vector(int size)
      : size(size),elem(new T[size])
      {

        space = size;
        for(int i = 0; i < size; i++){

            elem[i] = 0;
        }
      }

      Vector(){

         size = 0;
         elem = 0;
         space = 0;

      }

      Vector(const Vector& other)
      {

        size = other.size;
        elem = new T[other.size];
        copyValues(other);
      }

      void copyValues(const Vector& other){

         for(int i = 0; i < size; i++){

            elem[i] = other.elem[i];
         }
      }

      Vector& operator=(const Vector& other){

         T *p = new T[other.size];

         for(int i = 0; i < other.size; i++){

            p[i] = other.elem[i];
         }
         delete[] elem;
         elem = p;
         size = other.size;
         return *this;
      }

      T& operator[](int i){

         return elem[i];
      }

       T operator[](int i)const{

         return elem[i];
      }

      int vectorSize(){

       return size;
      }

      void reserve(int amount){

         if(amount <= space){
            return;
         }
         T *p = alloc.allocate(amount);
         for(int i = 0; i < size; i++){

            alloc.construct(&p[i],elem[i]);
         }
          for(int i = 0; i < size; i++){

            alloc.destroy(&elem[i]);
         }

         alloc.deallocate(elem,space);

         elem = p;
         space = amount;
      }

      void resize(int newSize,T val = T()){

         reserve(newSize);
         for(int i = size; i < newSize; i++){

            alloc.construct(&elem[i],val);
         }
         for(int i = newSize; i < size; i++){

            alloc.destroy(&elem[i]);
         }
         size = newSize;
      }

      void push_back(const T& val){

           if(space == 0){

            reserve(8);
           }
           if(size == space){

            reserve(2 * space);
           }
           alloc.construct(&elem[size],val);
           size++;

      }

};

class hey{

  public:
      int a;
      int b;

      hey(){

       a = 7;
       b = 7;
      }
      hey(int x,int y){

       a = x;
       b = y;

      }
      hey(const hey& other){

       a = other.a;
       b = other.b;

      }

      hey& operator=(const hey& other){


       a = other.a;
       b = other.b;
       return (*this);
      }

};

int main()
{
   Vector<hey> sample;
   hey h(5,3);
   hey b(7,3);
   hey c(8,2);
   sample.push_back(h);
   sample.push_back(b);
   sample.push_back(c);

   sample[0].a = 9;

   for(int i = 0; i < sample.vectorSize(); i++){

      cout << sample[i].a << endl;
   }
}
The object passed to push_back is copied on line 123.

 
alloc.construct(&elem[size],val);
but how come it takes & the address of the object rather than by value?
also while I'm here what is the difference between deallocate and destroy?

I thought they would practically do the same thing?
Last edited on
val is passed by reference for the same reason that the argument to push_back was passed by reference, namely to avoid unnecessary copies.

destroy() destroys the object but doesn't deallocate the memory so you could still reuse the same memory to construct a new object using construct() if you wanted.
Topic archived. No new replies allowed.