= 연산자가 정의되지 않은 구조체에서 작동하는 이유는 무엇입니까?
간단한 예를 살펴 보겠습니다.
struct some_struct {
std::string str;
int a, b, c;
}
some_struct abc, abc_copy;
abc.str = "some text";
abc.a = 1;
abc.b = 2;
abc.c = 3;
abc_copy = abc;
그러면 abc_copy는 .. 의 정확한 복사본 입니다 abc
. = 연산자 를 정의 하지 않고 어떻게 가능 합니까?
(일부 코드 작업을 할 때 놀랐습니다 ..)
이 네 가지 메서드 (C ++ 11의 경우 6 개)를 정의하지 않으면 컴파일러에서 자동으로 생성합니다.
- 기본 생성자
- 생성자 복사
- 할당 연산자
- 폐물 소각로
- 생성자 이동 (C ++ 11)
- 이동 할당 (C ++ 11)
이유를 알고 싶다면?
C와의 하위 호환성을 유지하는 것입니다 (C 구조체는 = 및 선언을 사용하여 복사 할 수 있기 때문입니다). 그러나 간단한 클래스를 더 쉽게 작성할 수 있습니다. 어떤 사람들은 "얕은 복사 문제"때문에 문제를 추가한다고 주장합니다. 이에 대한 나의 주장은 소유 한 RAW 포인터가있는 클래스를 가져서는 안된다는 것입니다. 적절한 스마트 포인터를 사용하면 문제가 사라집니다.
기본 생성자 (다른 생성자가 정의되지 않은 경우)
컴파일러 생성 기본 생성자는 기본 클래스 기본 생성자를 호출 한 다음 각 멤버 기본 생성자를 호출합니다 (선언 된 순서대로).
소멸자 (소멸자가 정의되지 않은 경우)
선언의 역순으로 각 멤버의 소멸자를 호출합니다. 그런 다음 기본 클래스의 소멸자를 호출합니다.
복사 생성자 (복사 생성자가 정의되지 않은 경우)
src 객체를 전달하는 기본 클래스 복사 생성자를 호출합니다. 그런 다음 src 개체 멤버를 복사 할 값으로 사용하여 각 멤버의 복사 생성자를 호출합니다.
할당 연산자
src 객체를 전달하는 기본 클래스 할당 연산자를 호출합니다. 그런 다음 src 개체를 복사 할 값으로 사용하여 각 멤버에서 할당 연산자를 호출합니다.
이동 생성자 (이동 생성자가 정의되지 않은 경우)
src 객체를 전달하는 기본 클래스 이동 생성자를 호출합니다. 그런 다음 src 개체 멤버를 이동할 값으로 사용하여 각 멤버의 이동 생성자를 호출합니다.
이동 할당 연산자
src 객체를 전달하는 기본 클래스 이동 할당 연산자를 호출합니다. 그런 다음 src 개체를 복사 할 값으로 사용하여 각 멤버에서 이동 할당 연산자를 호출합니다.
다음과 같은 클래스를 정의하면 :
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
};
컴파일러가 빌드 할 내용은 다음과 같습니다.
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;
}
};
C ++에서 구조체는 멤버가 기본적으로 개인 액세스가 아닌 공용으로 설정되는 클래스와 동일합니다.
C ++ 컴파일러는 또한 제공되지 않는 경우 클래스의 다음 특수 멤버를 자동으로 생성합니다.
- 기본 생성자 -인수 없음, 기본값은 모든 것을 초기화합니다.
- 복사 생성자 -즉, 동일한 클래스의 다른 객체에 대한 참조를받는 클래스와 이름이 같은 메서드. 모든 값을 복사합니다.
- 소멸자 -개체가 소멸 될 때 호출됩니다. 기본적으로 아무것도하지 않습니다.
- 할당 연산자 -하나의 구조체 / 클래스가 다른 구조체에 할당 될 때 호출됩니다. 위의 경우 호출되는 자동 생성 메서드입니다.
이 동작은 C와의 소스 호환성을 유지하기 위해 필요합니다.
C는 연산자를 정의 / 재정의하는 기능을 제공하지 않으므로 일반적으로 구조체는 = 연산자로 복사됩니다.
그러나 그것은 정의되어 있습니다. 표준에서. 연산자 =를 제공하지 않으면 하나가 제공됩니다. 그리고 기본 연산자는 각 멤버 변수를 복사합니다. 그리고 각 구성원을 복사하는 방법을 어떻게 알 수 있습니까? 연산자 = (정의되지 않은 경우 기본적으로 제공됨 ...)를 호출합니다.
할당 연산자 ( operator=
)의 C ++ 구조체 또는 클래스에 대한 내재적 생성 기능 중 하나이다.
다음은 암시 적으로 생성 된 4 개의 멤버를 설명하는 참조입니다.
http://www.cs.ucf.edu/~leavens/larchc++manual/lcpp_136.html
간단히 말해서, 암시 적으로 생성 된 멤버는 멤버 별 단순 복사를 수행합니다 . 링크 된 페이지의 긴 버전은 다음과 같습니다.
암시 적으로 생성 된 할당 연산자 사양은 필요한 경우 다음과 같습니다. 사양은 결과가 할당되는 객체 (
self
)이고self
post-stateself
"의 추상 값 값이 인수의 추상 값 값과 동일 하다고 말합니다from
.
// @(#)$Id: default_assignment_op.lh,v 1.3 1998/08/27 22:42:13 leavens Exp $
#include "default_interfaces.lh"
T& T::operator = (const T& from) throw();
//@ behavior {
//@ requires assigned(from, any) /\ assigned(from\any, any);
//@ modifies self;
//@ ensures result = self /\ self" = from\any\any;
//@ ensures redundantly assigned(self, post) /\ assigned(self', post);
// thus
//@ ensures redundantly assigned(result, post) /\ assigned(result', post);
//@ }
컴파일러는 명시 적으로 직접 정의하지 않으면 일부 멤버를 합성합니다. 할당 연산자는 그중 하나입니다. 복사 생성자는 또 다른 것이며 소멸자도 얻습니다. 또한 자체 생성자를 제공하지 않으면 기본 생성자를 얻습니다. 그 외에도 나는 다른 것이 확실하지 않지만 다른 사람이있을 수 있다고 믿습니다 (280Z28에 의해 제공된 답변의 링크는 그렇지 않은 것을 암시하며 지금 어디서 읽었는지 기억할 수 없으므로 아마도 4 일뿐입니다).
구조체는 기본적으로 메모리의 구성 요소를 연결 한 것입니다 (정렬을 위해 가능한 패딩이 내장되어 있음). 하나의 구조체에 다른 구조체의 값을 할당하면 값이 처리됩니다.
'programing' 카테고리의 다른 글
스플라이스가 제대로 작동하지 않음 내 객체 목록 VueJs (0) | 2022.08.09 |
---|---|
GET 매개 변수에 허용되는 문자 (0) | 2021.01.19 |
프로세스에서 반환 값 가져 오기 (0) | 2021.01.19 |
aov에서 p- 값 추출 (0) | 2021.01.19 |
최대 절전 모드에서 JTA, JPA 및 일반 JDBC의 차이점 (0) | 2021.01.19 |