2009-05-19 3 views
3

(G ++에서) 컴파일하고 다음 코드를 실행하면 "Foo :: Foo (int)"가 인쇄됩니다. 그러나 복사 생성자와 할당 연산자를 비공개로 만들면 다음 오류로 컴파일되지 않습니다. "오류 : 'Foo :: Foo (const Foo &)'가 비공개입니다. 런타임시 표준 생성자 만 호출하는 경우 복사 생성자가 필요한 이유는 무엇입니까?컴파일러 액세스 규칙

#include <iostream> 

using namespace std; 

struct Foo { 
    Foo(int x) { 
     cout << __PRETTY_FUNCTION__ << endl; 
    } 


    Foo(const Foo& f) { 
     cout << __PRETTY_FUNCTION__ << endl; 
    } 

    Foo& operator=(const Foo& f) { 
     cout << __PRETTY_FUNCTION__ << endl; 
     return *this; 
    } 
}; 

int main() { 
    Foo f = Foo(3); 
} 

답변

15

복사 생성자 여기서 사용된다

Foo f = Foo(3); 

이 동등하다 :

Foo f(Foo(3)); 

여기서 괄호 상기 제 1 세트의 재 복사 생성자 호출. 컴파일러는 복사 생성자 호출을 멀리 최적화하기 위해 선택할 수

Foo f(3); 

주 만 복사 생성자는 여전히 (즉 개인되지 않음)를 사용할 수 있어야합니다 : 당신은 말함으로써이 문제를 피할 수 있습니다. C++ 표준은 특히 복사 생성자의 구현이 실제로 무엇을하든이 최적화 (12.8/15 절 참조)를 허용합니다.

+0

복사 생성자를 사용한다고 주장하면 출력에서 ​​왜 보이지 않습니까? 원래의 포스터는 명확하게 :: Foo (int) 만 호출되었음을 명시했습니다. – KIV

+0

@ Neil하지만 복사 생성자가 명확하게 뭔가를하므로 컴파일러가이를 최적화하지 못하는 것 같습니다. –

+1

@Matthew : 아니요. 표준을 통해 명시 적으로 호출을 최적화 할 수 있으므로 컴파일러는 어떤 것도 신경 쓰지 않습니다. 부작용. 그 소금 가치가있는 현대 컴파일러 *는이 호출을 최적화합니다. 다른 한편, 표준은 통화가 여전히 가능해야한다는 것을 명확하게 명시합니다. 따라서 닐의 설명은 옳고 그 요점이다. –

2

컴파일러가 임시 생성을 피할 때 표준 최적화가 허용하는 결과입니다. 컴파일러는 부작용 (예 : IO의 경우)이 있더라도 간단한 구성으로 구성 및 할당을 바꿀 수 있습니다.

사실 프로그램이 잘못되었거나 상황에 의존해서는 안되는 경우 컴파일러가이 최적화를 수행하는지 여부. 그 이유는

Foo f = Foo(3); 

에는 복사 생성자가 필요합니다. 및

Foo f(3); 

않습니다. 아마 같은 바이너리 코드로 이어질지라도. 12.8.15

When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.111) This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):

— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function’s return value

— when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy

에서

견적 페이지의 "반환 값 최적화".