오래된 alloctaor :: construct와 새로운 것과 명시적인 생성자 사이의 차이점은 무엇입니까?


15

아시다시피 std::allocator<T>::construct이전 버전의 C ++에서는 두 개의 매개 변수 만 사용합니다. 첫 번째는 생성되지 않은 원시 메모리에 대한 포인터이며, 여기서 우리는 유형의 객체를 구성하려고 T하며, 두 번째는 해당 객체를 초기화하기위한 요소 유형의 값입니다. 따라서 복사 생성자가 호출됩니다.

struct Foo {
    Foo(int, int) { cout << "Foo(int, int)" << endl; }
    /*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};

int main(int argc, char* argv[]) {


    allocator<Foo> a;
    Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
//  Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98

    a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
    a.construct(p, 10);// works on both
    a.destroy(p);
    a.destroy(p + 1);
    a.deallocate(p, 200);



    std::cout << std::endl;
}
  • C ++ 98 a.construct(p, 10)에서 복사 생성자를 호출하지만 C ++ 11 이상에서 정수를 사용하는 생성자를 호출하는 이유는 무엇입니까?

  • 생성자 Foo(int)explicit이러한 호출에서 작동하는 경우에도 일부 복사 제거 최적화로 인해 C ++ 11에서 이것이 의미합니까? C ++ 11에서 작동 a.construct(p, 5)하더라도 생성자가 explicit확실하다는 것은 C ++ 98에서 작동하지 않는다는 것입니다 Foo(int)입니다 explicit.

  • 그렇다면 어떤 종류의 copy-elision최적화 를 비활성화하여 해당 명령문을 컴파일 하면 컴파일러가 실패합니까? 감사합니다.


3
짧은 대답 : C ++ 11까지는 완벽한 포워드 가 없었습니다 . 자세한 내용은 @flyx에서 제공합니다. 복사 제거필요하지 않습니다 ( 값별 또는 값별 반환 없음).
Daniel Langr

답변:


13

construct C ++ 11에서 선언이 변경 되었기 때문입니다 .

void construct( pointer p, const_reference val );  (1)  (until C++11)
template< class U, class... Args >
void construct( U* p, Args&&... args );            (2)  (since C++11)

첫 번째 선언은 복사 생성자를 호출하고 두 번째 선언은 주어진 인수 목록과 일치하는 생성자를 호출합니다. 이것은 복사 생성자 일 수 있지만 코드에서 본 다른 생성자 일 수도 있습니다.

a.construct(p, 10)10은 암시 적으로 생성자 를 Foo통해 변환 되기 때문에 C ++ 98에서 복사 생성자를 호출합니다 Foo(int). 이 변환은 C ++ 11에서 필요하지 않습니다 int(C ++ 98에서 변환하는 데 사용 된 생성자). 이 또한 추가 할 때 코드가 98 C ++로 작업을하지 않는 이유입니다 explicit- 그것은 변환 할 수 없습니다 10A를 Foo다음.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.