[따배씨++]Chapter4. 변수범위와 더 다양한 변수형
카테고리: Cpp
태그: Programming
인프런에 있는 홍정모님의 홍정모의 따라하며 배우는 C++ 강의를 듣고 정리한 내용입니다.
🚆 지역변수의 범위와 지속기간 - scope vs duration
scope vs duration : 동적할당 가면 달라짐
int a = 3;
int a = 5; // error
int apple = 5;
{
int apple = 10;
cout << apple << endl; // 10
cout << ::apple << endl; // 5
}
cout << apple << endl; // 5
- 같은 범위 (scope{}) 내에서 동일한 이름의 변수는 사용 불가
- 변수 이름이 같다면, 가장 가까운 범위의 변수가 우선 (name hiding)
- 범위를 벗어나면 변수 데이터는 수명이 다해 사라짐
namespace work1
{
int a = 5;
}
namespace work2
{
int a = 3;
}
cout << work1::a << endl; // 5
cout << work2::a << endl; // 3
- namespae를 통해 충돌 방지
- nested namespace 가능
🚆 전역 변수, 정적 변수 & 내부 연결, 외부 연결
global vs static
global variable
int a = 5; // main 밖에서 선언
int main()
{
...
}
- 다른 cpp파일에서도 값이 바꾸는 경우도 많아서 관리하기가 너무 빡셈
- 지속기간이 없음. 프로그램 종료 때 사라짐
int g_a = 5;
이런 식으로 g_로 표기해주면 좋음- 사용하려면 const로, 되도록 안 쓰는 게 최고
static variable
void doSomething()
{
static int a = 1;
++a;
cout << a << endl;
}
int main()
{
doSomething(); // 2
doSomething(); // 3
doSomething(); // 4
doSomething(); // 5
}
- os로 부터 받은 메모리가 static(정적) ➡️ 메모리 공유
- 초기화는 한 번만 시행되는데, 반드시 있어야 함
- 해당 block (범위) 밖에서는 접근 불가
- 함수가 몇 번 호출됐나 등 디버깅할 때 유용함
- 범위가 벗어나도 메모리 유지
- global varible 보다 static local variable 선호
Internal vs External Linkage
Internal Linkage
static int g_a = 5;
- 다른 cpp파일에서 접근 불가능 (링커에 노출 X)
External Linkage
namespace Constatns // myConstans.h file
{
extern const double pi = 3.141592;
extern const double gravity = 9.8;
}
void doSomething(); // extern 생략
int main()
{
cout << Constatns::pi << endl;
doSomething();
}
void doSomething()
{
cout << 5 << endl;
}
- 함수는 extern이 default값 (static 설정도 가능)
- 전방 선언의 의미 : extern이니 어딘가에 몸통이 있다. 컴파일러 너가 알아서 찾아 써라
- 만약 몸통이 없으면? 빌드는 되는데 컴파일에러남
- 전역 변수 앞에 extern 붙이면 메모리 공유
- extern 없어도 사용은 가능한데 값 복사해와서 사용 ➡️ extern 명시로 메모리 최적화 가능
🚆 using문과 모호성 (ambiguity)
namespace a
{
int my_var = 123;
}
namespace b
{
int my_var = 123;
}
int main()
{
using namespace a;
using namespace b;
cout << my_var << endl; // error: my_var is ambiguous
}
- using namespace a : 정의 안 되어 있으면 a 가서 찾아봐라.
- 변수나 함수의 이름이 같은 경우가 생김
- 특히 전역으로 사용하는 using이나 헤더 파일에서 using 넣어 버리면 에러 가능성이 커짐
- using namespace는 risk 존재
정 쓰고싶으면
{
using namespace a;
cout << my_var << endl; // error X
}
{
using namespace b;
cout << my_var << endl;
}
🚆 Auto 키워드와 자료형 추론 - Type Inference
auto add(int x, int y)
{
return x + y;
}
int main()
{
auto a = 1 + 2.0; // a : double
}
- 변수, 함수 리턴에 사용 가능
- 함수 parameter에는 사용 불가
🚆 암시적 형변환과 명시적 형변환
Implicit Type Conversion
double a = 3.14;
int b = a;
cout << b << endl; // 3
cout << 5u - 10 << endl; // 4294967291
- 컴파일러가 알아서 타입 변환
- 더 작은 타입으로 변환 시 데이터 손실
- 주의) unsinged 가 우선순위 더 높음
Explicit Type Conversion
int a = int(3.14);
int a = static_cast<int>(3.14); // 형 변환 강조하기 좋음
- 프로그래머가 직접 변환
- 강조하고 싶은 경우 static_cast<> (기능은 같음)
🚆 문자열 소개 - std::String
const string my_hello = "Hello, world";
const char my_strs[] = "Hello, world";
#include <string>
- 기본 자료형처럼 사용할 수 있게 구현됨
- 추가적인 편리한 기능들도 있음
- ex) str1 + str2, length(), …
🚆 Enumerated Types
복잡한 이름들 말고 인덱스로 들고 다니고 싶다..!
enum Color
{
COLOR_BLACK, // 0
COLOR_RED, // 1
COLOR_BLUE, // 2
COLOR_GREEN, // 3
};
int main()
{
Color paint = COLOR_BLUE;
Color apple = Color(1); // apple = red
cout << paint << endl; // 2 출력
}
- 모든 데이터 타입 가능
- 실제로는 정수형으로 움직임
- 전역 변수처럼 작동하기 때문에 동일한 이름의 변수 명 사용 불가
- Color1_enum의 black, Color2_enum의 black 이 같다고 인식 (내부적으로 0 == 0)
Enum Class!
enum class color1
{
red,
};
enum class color2
{
red,
};
int main()
{
color1 red1 = color1::red;
color2 red2 = color2::red;
if (red1 != red2) // error : 비교 불가
cout << "differ" << endl;
}
- 동일한 이름의 변수 구별 & 사용 가능
- 정수로 작동 X
🚆 기존 자료형에 가명 붙여주기 - typedef
double distance;
typedef double distance_t; // 컴파일러 입장에서 같음
distance_t home2work;
typedef vector<pair<string, int>> pairlist_t;
using pairlist_t = vector<pair<string, int>>;
- 이해하기 쉬움 (메모겸 주소겸..)
- 자료형이 복잡할 경우 유용함 (using쓰기도 함)
🚆 구조체 - struct
struct Person {
// default initialize
double height = 170.0;
float weight = 100.0;
int age = 25;
string name = "Mr. Incredible";
void print()
{
cout << height << "" << weight << ... << endl;
}
};
int main()
{
Person me{ 200.0, 100.0, 20, "Jack Jack" };
cout << me.age << endl; // .(dot) operator로 접근
Person my_friend(me); // static variable 있으면 조심해야 함
}
- 여러가지 자료형들을 하나로 묶어서 관리할 수 있다.
- c++는 구조체에 함수도 가능
- nested struct 가능
- struct 와 class의 차이는 default가 public이냐 private이냐 라고 함
- struct끼리 assignment는 조심해서 해야 함
구조체 자료형 크기 - Padding
struct Employee // 2 + (2) + 4 + 8 = 16 padding
{
short id; // 2 bytes
int age; // 4bytes
double wage; // 8 bytes
};
int main()
{
cout << sizeof(Employee) << endl; // 16 bytes
}
- 2 bytes 껴있으면 다루기가 좀 어렵나 봄..
- 컴파일러가 4 bytes 처럼 들고다님
- 변수들의 size, 순서가 최적화에 영향을 미침
댓글 남기기