std::vector의 emplace_back 자체가 빈 클래스 할당한 뒤에 이동하는게 아님. 빈 vector에서 emplace_back 하는건 다들 알고있는 대로 됨.
문제는 vector의 사이즈가 >0 일때임. 이 과정에서는 resize를 먼저 하기 때문에 재할당 후 move를 하기 때문에 resize로 빈 클래스 생성 후에 이전 메모리에 있던 클래스들을 move 생성자로 넣음. 아 move 였나....
여튼 그래서 emplace_back으로 생성된 애가 문제가 아니라 기존에 있던 애들이 이동하면서 문제가 발생했었음.
그냥 이동생성자 잘못만들었다는거 아니였음?
ㅇㅇ 이동생성자에서 socket pointer를 NULL로 안바꿈. 애초에 이동생성자를 신경 별로 안쓰고 있었음
대충 개념은 제대로 알고계신데 기술적으로 조금더 nitpick을 하자면, .size() == .capacity() 인 상황에서도 "빈 클래스" 생성은 안하게됨. 내부에서 .resize()를 호출한다면 글 쓰신거처럼 동작하겠지만 위 상황이 닥치면 내부에서 .reserve()를 부르게 되는데, .reserve()는 클래스 생성은 안하고 (현재 capacity * 상수) 만큼의 "초기화 되지 않은 메모리" 할당후 이곳에 객체들이 이사를 가게됨. 그리고 이사를 갈때도 is_nothrow_move_constructible_v(object) == true 일때만 이동생성자를 부르게되고 false일때는 어쩔수없이 복사 생성자를 부르게됨.
그리고 이런 vector 내부 동작을 떠나서 객체가 참조하는게아니고 "소유"하는 개념일때 raw pointer를 사용하시면 수명관리가 상당히 까다롭게 되니 특별한 이유가 있으신게 아닌이상 대부분 상황에서 스마트포인터를 쓰시면 이런 버그는 미연에 방지가 가능해집니다.
즉 unique_ptr 같은 애들을 쓰는게 좋다는 이야기져?
네. raw pointer로 구현하시면 copy/move constructor/assignment operator, destructor 적어도 다섯개의 함수에서 수명관리를 직접 해줘야되는데 unique_ptr이나 shared_ptr은 그런거 일일히 안만들어도 알아서 해결해주니까요.
그건 맞져. 생각 못했음 ㅋㅋㅋ