본문 바로가기

C++ (learncpp)/C++ Basics

1.4 — Variable assignment and initialization

이전 단원(1.3 -- 개체 및 변수 소개 (1.3 -- Introduction to objects and variables))에서 값을 저장하는 데 사용할 수 있는 변수를 정의하는 방법을 다루었습니다. 이 수업에서는 실제로 값을 변수에 넣고 그 값을 사용하는 방법을 살펴보겠습니다.

상기시켜드리자면, 먼저 x라는 단일 정수 변수를 할당한 다음 y 및 z라는 두 개의 정수 변수를 추가로 할당하는 짧은 스니펫이 있습니다.

 

int x; // define an integer variable named x
int y, z; // define two integer variables, named y and z

 

변수 할당 (Variable assignment)

변수가 정의된 후 = 연산자를 사용하여 변수에 값을 (별도의 문에서) 지정할 수 있습니다. 이 프로세스를 줄여서 복사 할당(또는 그냥 할당)이라고 합니다.

 

int width; // define an integer variable named width
width = 5; // copy assignment of value 5 into variable width

// variable width now has value 5

 

복사 할당(Copy assignment)은 = 연산자의 오른쪽에 있는 값을 연산자의 왼쪽에 있는 변수에 복사하기 때문에 명명됩니다. = 연산자를 할당 연산자라고 합니다.

다음은 할당을 두 번 사용하는 예입니다.

 

#include <iostream>

int main()
{
	int width;
	width = 5; // copy assignment of value 5 into variable width

	// variable width now has value 5

	width = 7; // change value stored in variable width to 7

	// variable width now has value 7

	return 0;
}

 

변수 width에 값 7을 할당하면 이전에 있던 값 5를 덮어씁니다. 일반 변수는 한 번에 하나의 값만 보유할 수 있습니다.

 

경고 (Warning)

신입 프로그래머가 저지르는 가장 흔한 실수 중 하나는 대입 연산자(=)와 등호 연산자(==)를 혼동하는 것입니다. 할당(=)은 변수에 값을 할당하는 데 사용됩니다. 같음(==)은 두 피연산자가 값이 같은지 여부를 테스트하는 데 사용됩니다.

 

초기화 (Initialization)

할당의 한 가지 단점은 적어도 두 개의 명령문이 필요하다는 것입니다. 하나는 변수를 정의하고 다른 하나는 값을 할당하기 위한 것입니다.

이 두 단계를 결합할 수 있습니다. 변수를 정의할 때 변수의 초기값을 동시에 제공할 수도 있습니다. 이것을 초기화라고 합니다. 변수를 초기화하는 데 사용되는 값을 이니셜라이저라고 합니다.

C++의 초기화는 놀라울 정도로 복잡하므로 여기서는 단순화된 보기를 제공합니다.

C++에서 변수를 초기화하는 4가지 기본 방법이 있습니다.

 

int a; // no initializer
int b = 5; // initializer after equals sign
int c( 6 ); // initializer in parenthesis
int d { 7 }; // initializer in braces

 

이니셜라이저가 제공되지 않는 경우는 다음 단원에서 다룰 것입니다(1.6 -- 초기화되지 않은 변수와 정의되지 않은 동작(1.6 -- Uninitialized variables and undefined behavior)).

위의 형식이 다른 간격으로 작성된 것을 볼 수 있습니다(예: int d{7};). 가독성을 위해 추가 공백을 사용하는지 여부는 개인 취향의 문제입니다.

 

복사 초기화 (Copy initialization)

등호 뒤에 이니셜라이저가 제공되면 이를 복사 초기화라고 합니다. 복사 초기화는 C 언어에서 상속되었습니다.

 

int width = 5; // copy initialization of value 5 into variable width

 

복사 할당과 매우 유사하게 이는 equals의 오른쪽에 있는 값을 왼쪽에 생성되는 변수와 복사합니다.

 

int와 같은 단순 유형의 경우 복사 초기화가 효율적입니다. 그러나 유형이 더 복잡해지면 복사 초기화가 비효율적일 수 있습니다.

직접 초기화 (Direct initialization)

괄호 안에 이니셜라이저가 제공되는 경우 이를 직접 초기화라고 합니다.

 

int width( 5 ); // direct initialization of value 5 into variable width

 

단순 데이터 유형(예: int)의 경우 복사 및 직접 초기화는 본질적으로 동일합니다. 더 복잡한 유형의 경우 직접 초기화가 복사 초기화보다 더 효율적인 경향이 있습니다.

 

중괄호 초기화 (Brace initialization)

불행히도 직접 초기화는 모든 유형의 초기화(예: 데이터 목록으로 개체 초기화)에 사용할 수 없습니다. 보다 일관된 초기화 메커니즘을 제공하기 위해 중괄호를 사용하는 중괄호 초기화(균일한 초기화 또는 목록 초기화라고도 함)가 있습니다.

중괄호 초기화는 세 가지 형식으로 제공됩니다.

 

int width { 5 }; // direct brace initialization of value 5 into variable width (preferred)
int height = { 6 }; // copy brace initialization of value 6 into variable height
int depth {}; // value initialization (see next section)

 

직접 및 복사 중괄호 초기화 기능은 거의 동일하지만 일반적으로 직접 형식이 선호됩니다.

중괄호 초기화에는 "축소" 변환을 허용하지 않는 추가 이점이 있습니다. 즉, 중괄호 초기화를 사용하여 안전하게 유지할 수 없는 값으로 변수를 초기화하려고 하면 컴파일러에서 경고 또는 오류가 발생합니다. 예를 들어:

 

int width { 4.5 }; // error: not all double values fit into an int

 

위의 스니펫에서 분수 부분(.5 부분)이 있는 숫자(4.5)를 정수 변수(소수 부분 없이 숫자만 보유할 수 있음)에 할당하려고 합니다. 복사 및 직접 초기화는 소수 부분을 삭제하여 값 4를 가변 너비로 초기화합니다. 그러나 중괄호 초기화를 사용하면 컴파일러에서 오류가 발생합니다(데이터 손실은 거의 원하지 않기 때문에 일반적으로 좋은 일입니다). 잠재적인 데이터 손실 없이 수행할 수 있는 변환이 허용됩니다.

 

모범 사례 (Best practice)

가능하면 중괄호를 사용하여 초기화하는 것이 좋습니다.

 

Q: C++는 복사, 직접 및 중괄호 초기화와 복사 할당을 제공합니다. 직접 또는 중괄호 할당이 있습니까?
(Q: C++ provides copy, direct, and brace initialization, and copy assignment. Is there a direct or brace assignment?)

아니요, C++는 직접 또는 중괄호 할당 구문을 지원하지 않습니다.

 

값 초기화 및 제로 초기화 (Value initialization and zero initialization)

변수가 빈 중괄호로 초기화되면 값 초기화가 수행됩니다. 대부분의 경우 값 초기화는 변수를 0으로 초기화합니다(주어진 유형에 더 적합한 경우 비어 있음). 제로화가 발생하는 경우 이를 제로 초기화라고 합니다.

 

int width {}; // zero initialization to value 0


Q: 언제 {0 } 대 {}로 초기화해야 하나요?

(Q: When should I initialize with { 0 } vs {}?)

실제로 해당 값을 사용하는 경우 명시적 초기화 값을 사용하십시오.

int x { 0 }; // explicit initialization to value 0
std::cout << x; // we're using that zero value

 

값이 일시적이고 대체될 경우 값 초기화를 사용하십시오.

int x {}; // value initialization
std::cin >> x; // we're immediately replacing that value

 

변수 초기화 (Initialize your variables)

생성 시 변수를 초기화합니다. 결국 특정 이유로 이 조언을 무시하고 싶은 경우를 찾을 수 있습니다(예: 많은 변수를 사용하는 코드의 성능이 중요한 부분). 선택이 의도적으로 이루어지기만 하면 괜찮습니다.

이 주제에 대한 더 많은 토론을 위해 Bjarne Stroustrup(C++ 창시자)와 Herb Sutter(C++ 전문가)가 직접 이 권장 사항을 작성했습니다.

우리는 1.6과에서 잘 정의된 값이 없는 변수를 사용하려고 하면 어떻게 되는지 탐구합니다 -- 초기화되지 않은 변수와 정의되지 않은 동작.

 

모범 사례 (Best practice)

생성 시 변수를 초기화합니다.

 

여러 변수 초기화 (Initializing multiple variables)

마지막 섹션에서 이름을 쉼표로 구분하여 단일 명령문에서 동일한 유형의 여러 변수를 정의하는 것이 가능하다는 점에 주목했습니다.

 

int a, b;

 

또한 모범 사례는 이 구문을 완전히 피하는 것입니다. 그러나 이 스타일을 사용하는 다른 코드를 만날 수 있으므로 피해야 하는 몇 가지 이유를 강화하는 것 외에 다른 이유가 없다면 이에 대해 조금 더 이야기하는 것이 여전히 유용합니다.

같은 줄에 정의된 여러 변수를 초기화할 수 있습니다.

 

int a = 5, b = 6; // copy initialization
int c( 7 ), d( 8 ); // direct initialization
int e { 9 }, f { 10 }; // brace initialization (preferred)

 

불행히도 프로그래머가 실수로 하나의 초기화 문을 사용하여 두 변수를 모두 초기화하려고 할 때 발생할 수 있는 일반적인 함정이 있습니다.

 

int a, b = 5; // wrong (a is not initialized!)

int a = 5, b = 5; // correct

 

맨 위 명령문에서 변수 "a"는 초기화되지 않은 상태로 남아 있으며 컴파일러는 불평할 수도 있고 그렇지 않을 수도 있습니다. 그렇지 않은 경우 프로그램이 간헐적으로 충돌하고 산발적인 결과를 생성하는 좋은 방법입니다. 초기화되지 않은 변수를 사용하면 어떤 일이 발생하는지 곧 더 자세히 이야기하겠습니다.

이것이 틀렸음을 기억하는 가장 좋은 방법은 직접 초기화 또는 중괄호 초기화의 경우를 고려하는 것입니다.

 

int a, b( 5 );
int c, d{ 5 };

 

이것은 값 5가 a 또는 c가 아닌 변수 b 또는 d를 초기화하는 데만 사용된다는 것을 조금 더 명확하게 보여줍니다.

 

reference : https://www.learncpp.com/cpp-tutorial/variable-assignment-and-initialization/