Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::vector::reserve call the copy constructor?

Tags:

c++

gcc

stl

vector

Why does the following code not work with g++ version 4.9.2? If I try to build it the compiler complains about the missing copy constructor in the line where the vector is told to reserve more memory.

#include <vector>

class Number
{
public:
    explicit Number(const int& i) : _value(i) {}

    Number(const Number& other) = delete;
    Number& operator=(const Number& other) = delete;

private:
    int _value;
};


int main(int argc, char** argv)
{
    std::vector<Number> numbers;
    numbers.reserve(8);

    return 0;
}

Why would the compiler even try to call the deleted copy constructor when the storage size of the vector is increased? There are no objects inside the vector anyway.

like image 267
ifschleife Avatar asked Dec 14 '14 15:12

ifschleife


1 Answers

The short answer is because the language standard says so. But that isn't interesting.

Reserve can call the copy constructor if there was data in the container.

Which branch of reserve it follows (no copy, or copy) is determined at run time, not compile time.

You are seeing a compile time error, not a run time error. You have stated that no code that can possibly cause your object to copy should be compiled.

The compiler does not analyze the spot where reserve is, prove to itself the vector is empty, use that to determine which branch of code reserve will run, then say "no problem". Instead, it compiles the function, which contains copies, and generates an error.

In theory, a container that allows pre-allocation (while empty) and emplace construction only (up to the pre-determined limit) would not require objects with any kind of copy or move construction. At the time the std container library was written, emplace construction was impractical, so this option does not exist in the std container library: prior to C++11, the only way to put objects into a vector was to copy it.

std::dynarray comes close, but it doesn't let you have the buffer be half-unused and filled gradually.

like image 181
Yakk - Adam Nevraumont Avatar answered Oct 03 '22 15:10

Yakk - Adam Nevraumont