1

I have the following code that mimics an elision testcase

class Obj
{
  public:
  int x = 0;
  Obj(int y) : x(y) {std::cout << "C\n"; }
  ~Obj() { std::cout << "D\n"; }
};

auto factory()
{
  std::vector<Obj> vec {1,2,3};
  
  std::cout<< &vec[0] << std::endl;
  
  return vec;
}

int main()
{
    auto vec = factory();
    
    std::cout<< &vec[0] << std::endl;
    
    for(auto& v : vec)
      std::cout << v.x << std::endl;
}

The output is unexpected, tho

C C C D D D

0x5640f1d43e80

0x5640f1d43e80

1 2 3 

D D D

Why Obj destructor is called if there's elision active ?

I see that the memory space of the first item is the same ( and constructor is not called ) So I would imagine that no memory has been copied. But if that's so, why (again) item destructors are called in the first place ?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Matteo Galeotti
  • 105
  • 1
  • 9
  • 1
    Before the vector is constructed, the initializer list is built first. All elements are then copied to the vector. You see the destruction of these temporary objects – Michael Veksler Feb 05 '22 at 10:04
  • @MichaelVeksler Oh, you are right. I was so focussed on elision that i forgot that. So if I go with emplace_back no temp items are actually created. Thank you. If you want to put this an answar I'll mark as resolved – Matteo Galeotti Feb 05 '22 at 10:09

1 Answers1

3

With the initializer list construction:

std::vector<Obj> vec {1,2,3};

First the initializer_list is constructed, with all 3 Obj objects. Only then is the constructor of std::vector invoked, coping the three objects. What you see as 3 destructor calls is actually the destruction of the initializer_list, not the vector object (which is in fact elided in this case).

Michael Veksler
  • 8,217
  • 1
  • 20
  • 33