I am learning to use C vectors, and I can't quite understand the output of the following program:
#include <iostream>
#include <vector>
using namespace std;
class Custom {
public:
int v;
Custom() = delete;
explicit Custom(int v) : v{v} {};
Custom(const Custom &) : v{4} {
}
friend ostream &operator<<(ostream &os, const Custom &th) {
os << "V is " << th.v << endl;
return os;
}
};
int main(int argc, char *argv[]) {
vector<Custom> c(2, Custom(3));
c[0].v = 5;
for (auto i: c) {
cout << i << endl;
}
}
I expected it to produce the output
V is 5
V is 4
But instead it produces
V is 4
V is 4
Am I missing something obvious? Thanks.
CodePudding user response:
This range based loop is making copies:
for (auto i: c) {
cout << i << endl;
}
And the copy constructor initializes v
to 4
(and does not make a copy):
Custom(const Custom &) : v{4} {
}
You can either implement a proper copy constructor or use references in the loop to get the desired output:
for (const auto& i: c) {
cout << i << endl;
}
I would suggest to do both, because this copy constructor is not doing a copy by any means. The compiler generated copy constructor should be fine:
Custom(const Custom &) = default;
PS: The fact that Custom
has a deleted default constructor is not really relevant for the posted code. Nowhere in the code a Custom
is default constructed. Also there is no iterator in your code. In the range based loop i
is a copy/reference of the elements in the vector, it is not an iterator.
CodePudding user response:
When you wrote:
for (auto i: c) //this uses copy constructor to copy initialize each element one by one from the vector
{
}
In the above snippet, each individual element of the vector is used to copy initiaize a temporary object named i
while iterating through the vector. And since you have the v{4}
in the constructor initializer list of the copy constructor you get the mentioned output.
To solve this you should replace: auto i: c
with auto &i: c
or const auto &i: c
as shown below:
for (const auto &i: c)
{
cout << i << endl;
}
Now the elements of the vector are not copied into i
. Instead they are references to the object themselves and so you'll get your expected output.