Strange vector behaviour

I don't understand why I see lines marked with arrows in console. I added c1 and c2 to vector with std::move. But when I was adding c3 and c4, I got extra copy constructor calling for c1 and for c1 and c2. WHY?!

Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
c1: meow!
c2: meow!
c3: meow!
c4: meow!
c1: !!!!
c2: !!!!
c1: ???? // <====
c3: ????
c1: ???? // <====
c2: ???? // <====
c4: ????
c1: say meow again
c2: say meow again
c3: say meow again
c4: say meow again


Source:

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
#include <iostream>
#include <string>
#include <vector>

class Cat {
public:
    Cat(std::string name) : myName(name) {
        std::cout << myName << ": meow!" << std::endl;
    }
    
    Cat(const Cat& other) {
        myName = other.myName;
        std::cout << myName << ": ????" << std::endl;
    }
    
    Cat(const Cat&& other) {
        myName = other.myName;
        std::cout << myName << ": !!!!" << std::endl;
    }
    
    void say() {
        std::cout << myName << ": say meow again" << std::endl;
    }
private:
    std::string myName;
};

int main()
{
    Cat c1("c1");
    Cat c2("c2");
    Cat c3("c3");
    Cat c4("c4");
    
    std::vector<Cat> cats;
    
    cats.push_back(std::move(c1));
    cats.push_back(std::move(c2));
    cats.push_back(c3);
    cats.push_back(c4);
    
    for (Cat & c : cats)
        c.say();
        
    return 0;
}
Last edited on
The vector is being resized. With the resizing, it is copied.

Allocate enough space to the vector to begin with and the resizing will no longer be necessary:

cats.reserve(10);, for example.
> But when I was adding c3 and c4, I got extra copy constructor calling for c1 and for c1 and c2. WHY?!

The move constructor for Cat is not declared as noexcept So the vector implementation is helpless; it can't safely move the objects from one buffer to another; it has to copy them.

See the notes for std::move_if_noexcept: https://en.cppreference.com/w/cpp/utility/move_if_noexcept

With a non throwing move constructor, we would see the expected behaviour:
http://coliru.stacked-crooked.com/a/aea6d327cdfe3c46
Last edited on
Topic archived. No new replies allowed.