문제

다음은 "C++ Gotchas" 책의 항목 56에서 발췌한 내용입니다.

마치 마치 마치 마치 마치 세 가지 다른 방식으로 작성된 y 객체의 간단한 초기화를 보는 것은 드문 일이 아닙니다.

Y a( 1066 ); 
Y b = Y(1066);
Y c = 1066;

사실,이 세 가지 초기화 모두 동일한 객체 코드가 생성 될 수 있지만 동일하지는 않습니다.A의 초기화는 직접 초기화로 알려져 있으며 정확히 기대할 수있는 것입니다.초기화는 y :: y (int)의 직접 호출을 통해 달성됩니다.

B와 C의 초기화가 더 복잡합니다.사실, 그들은 너무 복잡합니다.이들은 모두 사본 초기화입니다.B의 초기화의 경우, 우리는 값 1066으로 초기화 된 유형 Y의 익명 임시를 작성하도록 요청하고 있습니다.그런 다음이 익명 임시를 클래스 y의 카피 생성자의 매개 변수로 사용하여 b를 초기화합니다. b.마지막으로, 우리는 익명의 임시를 위해 소멸자를 부릅니다.

이를 테스트하기 위해 데이터 멤버(마지막에 첨부된 프로그램)를 사용하여 간단한 클래스를 수행했는데 결과는 놀라웠습니다.c의 경우 책에서 제시한 대로가 아니라 복사 생성자에 의해 객체가 생성된 것으로 보인다.

언어 표준이 변경되었는지 아는 사람이 있습니까? 아니면 이것이 단순히 컴파일러의 최적화 기능입니까?저는 Visual Studio 2008을 사용하고 있었습니다.

코드 샘플:

#include <iostream>

class Widget
{
    std::string name;
public:
    // Constructor
    Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
    // Copy constructor
    Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
    // Assignment operator
    Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};

int main(void)
{
    // construct
    Widget a("a");
    // copy construct
    Widget b(a);
    // construct and assign
    Widget c("c"); 
    c = a;
    // copy construct!
    Widget d = a;
    // construct!
    Widget e = "e";
    // construct and assign
    Widget f = Widget("f");

    return 0;
}

산출:

Constructing Widget a

Copy constructing Widget from a

Constructing Widget c
Assigning Widget from a to c

Copy constructing Widget from a

Constructing Widget e

Constructing Widget f
Copy constructing Widget from f

저는 d와 e를 구성한 결과에 가장 놀랐습니다.정확히 말하면 빈 객체가 생성된 다음 객체가 생성되어 빈 객체에 할당될 것으로 예상했습니다.실제로 객체는 복사 생성자에 의해 생성되었습니다.

도움이 되었습니까?

해결책

구문

X a = b;

A와 B가 유형 X 인 경우는 항상 사본 구성을 의미했습니다. 다음과 같은 변형이 무엇이든

X a = X();

사용되며, 과제는 없으며 결코 없었습니다. 구성 및 할당은 다음과 같습니다.

X a;
a = X();

다른 팁

컴파일러는 사례를 최적화하도록 허용됩니다. b 그리고 c 동일하다 a.또한 복사 생성 및 할당 연산자 호출은 어쨌든 컴파일러에 의해 완전히 제거될 수 있으므로 표시되는 내용은 다른 컴파일러나 심지어 컴파일러 설정에서도 반드시 동일하지는 않습니다.

C ++ 17 기준으로,이 세 가지 모두 ~이다 동등한 (그렇지 않다면 Y::Y(int) ~이다 explicit, 단순히 허용하지 않습니다 c) 종종 불리는 것 때문입니다 필수 사본 elision.

조차 Y c = 1066; 하나만 생성합니다 Y 암시 적 변환의 결과 때문에 개체 Y 초기화에 사용되는 홍보입니다 c 임시를 창조하기보다는.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top