당신은 당신을 위해 그들을 생성합니다 컴파일러 (C++ 11에 여섯)이 네 가지 방법을 정의하지 않으면 :
- 기본 생성자
- 복사 생성자
- 할당 연산자
을
- 소멸자
- 이동 생성자 (C++ 11)
- 이동 지정 (C++ 11)
이유를 알고 싶다면?
C와의 하위 호환성을 유지합니다 (C 구조체는 = 및을 사용하여 복사 가능하므로). 그러나 이것은 또한 간단한 클래스를 작성하는 것을 더 쉽게 만듭니다. 일부는 "얕은 복사 문제"때문에 문제를 추가한다고 주장합니다. 내 주장은 그것에 소유 된 RAW 포인터가있는 클래스를 가져서는 안된다는 것입니다. 적절한 스마트 포인터를 사용하면 문제가 사라집니다.
기본 생성자 (다른 생성자가 정의되지 않은 경우)
(그들이 선언 된 순서대로) 기본 클래스의 기본 생성자 및 각 구성원의 기본 생성자를 호출합니다 컴파일러 생성 된 기본 생성자 (더 소멸자 정의되지 않은 경우)
소멸자
선언의 역순으로 각 부재의 소멸을 호출한다. 그런 다음 기본 클래스의 소멸자를 호출합니다. (더 복사 생성자가 정의되지 않은 경우)
는 복사 생성자
는 SRC 객체를 전달 기본 클래스의 복사 생성자를 호출합니다. 그런 다음 src 객체 멤버를 복사 할 값으로 사용하여 각 멤버의 복사본 생성자를 호출합니다.
할당 연산자
는 SRC 객체를 전달 기본 클래스 할당 연산자를 호출합니다. 그런 다음 src 객체를 복사 할 값으로 사용하여 각 멤버에서 대입 연산자를 호출합니다.
이동 생성자 (더 이동 생성자가 정의되지 않은 경우)
는 SRC 객체를 전달 기본 클래스 이동 생성자를 호출합니다. 그런 다음 src 객체 멤버를 이동할 값으로 사용하여 각 멤버의 move 생성자를 호출합니다.
이동 할당 연산자
는 SRC 객체를 전달 기본 클래스 이동 할당 연산자를 호출합니다. 그런 다음 src 객체를 복사 할 값으로 사용하여 각 멤버의 이동 대입 연산자를 호출합니다.
이 같은 클래스를 정의하는 경우 :
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
// Conceptually two different versions of the default constructor are built
// One is for value-initialization the other for zero-initialization
// The one used depends on how the object is declared.
// some_struct* a = new some_struct; // value-initialized
// some_struct* b = new some_struct(); // zero-initialized
// some_struct c; // value-initialized
// some_struct d = some_struct(); // zero-initialized
// Note: Just because there are conceptually two constructors does not mean
// there are actually two built.
// value-initialize version
some_struct()
: some_base() // value-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it
// PODS not initialized
, str2()
{}
// zero-initialize version
some_struct()
: some_base() // zero-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it.
, a(0)
, b(0)
, c(0) // 0 is NULL
, str2()
// Initialize all padding to zero
{}
some_struct(some_struct const& copy)
: some_base(copy)
, str1(copy.str1)
, a(copy.a)
, b(copy.b)
, c(copy.c)
, str2(copy.str2)
{}
some_struct& operator=(some_struct const& copy)
{
some_base::operator=(copy);
str1 = copy.str1;
a = copy.a;
b = copy.b;
c = copy.c;
str2 = copy.str2;
return *this;
}
~some_struct()
{}
// Note the below is pseudo code
// Also note member destruction happens after user code.
// In the compiler generated version the user code is empty
: ~str2()
// PODs don't have destructor
, ~str1()
, ~some_base();
// End of destructor here.
// In C++11 we also have Move constructor and move assignment.
some_struct(some_struct&& copy)
// ^^^^ Notice the double &&
: some_base(std::move(copy))
, str1(std::move(copy.str1))
, a(std::move(copy.a))
, b(std::move(copy.b))
, c(std::move(copy.c))
, str2(std::move(copy.str2))
{}
some_struct& operator=(some_struct&& copy)
// ^^^^ Notice the double &&
{
some_base::operator=(std::move(copy));
str1 = std::move(copy.str1);
a = std::move(copy.a);
b = std::move(copy.b);
c = std::move(copy.c);
str2 = std::move(copy.str2);
return *this;
}
};
이것은 아주 훌륭하게 좋은 대답이지만 이미 스마트 포인터를 사용한 예를보고 싶습니다. 나는 결코 auto_ptr에서 놀랐다. – Hamy
@Hamy : 이것은 스마트 포인터를 만드는 데 필요한 정보이다. 똑똑한 포인터를 사용한다면 실제로 걱정할 필요가 없습니다. 클래스에 RAW 소유 포인터가있는 경우 위의 내용 만 신경 써야합니다. –
이 답변은 [초기화] (http://en.cppreference.com/w/cpp/language/initialization) 유형을 혼란스럽게합니다. 이니셜 라이저가 없으면 struct는 [* default initialized *] (http://en.cppreference.com/w/cpp/language/default_initialization)가됩니다. POD 유형 멤버는 불확정 값을 가정합니다. 비어있는 초기화자를 사용하면 구조체는 [* value initialized *] (http://en.cppreference.com/w/cpp/language/value_initialization) 될 것입니다. POD 유형 멤버는 [* zero initialized *] (http : //en.cppreference.com/w/cpp/language/zero_initialization). –