복사 생략, 이동 생성자

하루공부·2024년 1월 19일
0

C++

목록 보기
10/25
post-thumbnail

C++ 아이콘 제작자: Darius Dan - Flaticon


복사 생략

class A {
int data_;
public:
A(int data) : data_(data) { std::cout << "일반 생성자 호출!" << std::endl; }
A(const A& a) : data_(a.data_) {
std::cout << "복사 생성자 호출!" << std::endl;
}
};
A c(A(2));  ==> 일반 생성자가 호출됨

위 예시에서 내가 생각한 것은 A(2)에서 일반 생성자 호출후 임시 객체에 c가 복사되며 복사생성자가 호출될 것을 예상했지만 아니네?
사실 굳이 임시 객체 1번 만들고 여기에 복사를 할 필요가 없다.
==> 그냥 A(2)를 c로 만들꺼면 처음부터 c자체를 A(2)로 만들어진 객체로 해버리자

그래서 컴파일러는 굳이 복사 생성을 하지 않고 만들어진 A(2) 자체를 c로 만든다

이것이 복사 생략이다.

  • 복사 생략을 하는 경우는 (함수의 인자가 아닌) 함수 내부에서 생성된 객체를 그대로 리턴할 때
    (경우에 따라 생략을 할 수 도 있고 안할 수 도 있다)
    ==> 그럼 안하면 우짜지... 비효율적인 복사가 많아 꼭 필요한데...


이동 생성자

  • C++ 11에는 우측값 레퍼런스를 파라미터로 갖는 생성자가 추가
    ==> 이동 생성자(move constructor)라고 한다.
  • 우측값 레퍼런스는 &를 2번 사용해서 정의한다. ==> A&& a
int&& r_b = 3; 우측값
int&& rr_b = a; // 불가능 , 좌측값
  • 이동 생성자를 호출하면 사라지는 값인 우측값을 계속 갖고 있는 것 처럼 보이는데
    우선 원본 객체에서 데이터를 가져와서 새로 생성될 객체에 할당하고 nullptr로 원본 객체는 사라지지 않고 접근을 못하게 한다.

    nullptr은 C++ 11 에 새로 추가된 키워드로, 기존의 NULL 대체
    포인터 주소값 0을 명확하게 표현


  • 이동 생성자 작성시 해당 클래스를 C++ 컨테이너에 적용할 때는 반드시 이동 생성자를 noexcept로 명시.
    • 먼저 그냥 복사 생성자로 vector의 할당한 메모리가 부족할 때 새로 공간을 할당하여 원소들 모두 복사를 한다.
      이 과정에서 예외가 일어난다면 새로 할당한 메모리를 소멸시킨후 예외를 전달하게 될 것이다.

    • 그런데 이동 생성자는 그럴 수 없다.
      복사 생성은 복사를 하고 새로운 공간에 할당해서 그 공간을 소멸시켜도 기존 원소는 존재하지만
      이동 생성의 경우 기존 메모리에서 원소들이 모두 이동되어 사라지기에
      섯불리 새 메모리를 해제를 하면 원소 자체가 사라진다.
      • 따라서 이동 생성자에서 예외 발생시 처리를 못한다.
        ==> 이동 생성자는 noexcept가 아닌 이상 사용이 불가하다.

참조
공부한 내용 복습

개인 공부 기록용 블로그입니다.
틀린 부분 있으다면 지적해주시면 감사하겠습니다!!

0개의 댓글