본문 바로가기

C ++

[C++] 2. 기초 문법 - 변수 타입, auto(타입 추론), 참조변수(&), 좌측값과 우측값, const(상수 처리)

#정리

#reference  - &참조변수

//포인터와 비슷하지만, 다른 개념으로 특정 변수를 간점 참조하게된다.

 - 값이 가지는 주소를 저장하는 것이 아닌 특정 변수(동일 메모리)의 새로운 별칭을 붙이는 것 이해하면 된다. 

//동일 값을 가진 변수이므로 함수에 사용되어도 변수의 변경 값이 유지되어, 전역변수 같은 효과를 볼 수 있다. 

 - swapRef(kor,eng); // 스왑 비교를 통해 알 수 있다.

** 주소를 나열할 때, 나오는 주소의 값의 순서를 보면 메모리 영역을 알 수 있다.

 - 힙 : 영역 주소가 증가 / 스택 : 영역 주소가 감소



#Lvalue,Rvalue -  좌측값 / 우측값 

//assign (=)을 기준으로 좌측에 있는 값을 좌측 값, 우측에 있는 값을 우측 값이라 한다.

 - a = b; //a / b 는 좌측값 , 우측값 모두 가능하다.

 - a = a*b; //연산 부분은 우측에만 오기 때문에 "우측 값"이라고 한다.

 - int& test01();//return int& - (lvalue)좌측값 가능

    >> test01() = 300; //실제로 할당되는 것은 아니지만, 할당하는 문법이 가능하다.
 - int test02();//return int - (rvalue)좌측값 불가

//우측값만 되는 값(연산 값)에 대한 참조타입은 &를 두 번 붙인다.
 - int &&ref_sum = math + 100;



#auto - 타입 추론 (JS의 let과 유사) 

//타입추론은 11버젼부터 가능하다.

 - auto c2 = 'B'; //char 

 - auto su2 = 100; =  auto math{99}; //int

 - auto name2 = "kim"; //string

//참조 타입의 변수의 값도 넣을 수 있다. 단, 동일 주소를 할당 받지는 않는다.

 - auto autoSu = ref_su1;

 - autoSu =99;//동일 주소를 받는게 아니기 때문에 다른 값에 영향을 미치지 않는다.
 - ref_su1 = 99;//값 할당 이후에는 별도의 값으로 auotSu에 영향을 미치지 않는다.

//단일 타입의 배열 생성도 가능하다. (auto로는 타입을 섞어서 초기화 할 수 없다.)
 - 값을 넣는 것은 동일하지만, 값에 접근하는(꺼내쓰는) 방법이 다르다.

 - sus[i] // error - 인덱스로 접근 안됨.

 - for(auto i=sus.begin();i!=sus.end();i++){//sus.begin() >> 첫번째 주소값 반환 >> i가 포인터 변수가 된다.

 - cout << i << " " << *i << endl; //값을 꺼내 올 때, 포인터 변수 필요

//함수 파라메터로 사용 불가
 - void test01(auto a); //error

 - 함수 리턴문에 auto 선언은 가능하나, 사용시 컴파일 오류가 발생하며, 대안은 decltype, template,lambda가 있다.
//구조체 혹은 클래스의 속성으로 사용불가.


#const - 상수 처리 

//1. 일반적인 상수 처리 const int su = 20;
 - su = 100;//read only error
//2. const int *pt_kor : 주소 변경 가능 / 값 변경 불가
 - const int* pt_kor = &kor; 
 - *pt_kor = 100; //read only error

//3. int* const pt_kor : 값 변경 가능, 주소 변경 불가
 - *pt_kor2 = 100; //주소를 못바꾸고 값을 바꿀수 있게 된다.
 - pt_kor2 = &eng2; //read only error 주소 변경 불가
//4. int* const pt_kor : 값 변경 불가, 주소 변경 불가
 - *pt_kor3 = 1000; //read only error 값 변경 불가
 - pt_kor3 = &eng3; //read only error 주소 변경 불가

 

 

 

 

#reference  - &참조변수

//포인터와 비슷하지만, 다른 개념으로 특정 변수를 간점 참조하게된다.

 - 값이 가지는 주소를 저장하는 것이 아닌 특정 변수(동일 메모리)의 새로운 별칭을 붙이는 것 이해하면 된다. 

//동일 값을 가진 변수이므로 함수에 사용되어도 변수의 변경 값이 유지되어, 전역변수 같은 효과를 볼 수 있다. 

 - swapRef(kor,eng); // 스왑 비교를 통해 알 수 있다.

 

--예문 참조--

더보기
#include <iostream>
using namespace std;

void swapRef(int &kor,int &eng);
void swapVar(int kor,int eng);

int main(int argc, char **argv)
{
	cout << "-----------------" << endl;
	
	int su = 10;
	//주소값을 담아두는 변수 타입 & - 포인터 * 와 비슷하다.
	int &ref_su1 = su;
	int &ref_su2 = su;
	cout << "su: " << su << endl;
	cout << "&ref_su1: " << ref_su1 << endl;
	cout << "&ref_su2: " << ref_su2 << endl;
	
	//주소가 같아서, 하나를 바꾸면 모두가 바뀐다.
	ref_su1 = 2000;
	cout << "su: " << su << endl;
	cout << "&ref_su1: " << ref_su1 << endl;
	cout << "&ref_su2: " << ref_su2 << endl;
	
	int kor = 99, eng=100;
	//swapVar(kor,eng);
	swapRef(kor,eng);//함수에 사용된 변수의 주소를 유지시켜준다. >> 전역변수 같은 효과
	cout << "kor: " << kor << endl;
	cout << "eng: " << eng << endl;
	
	
	return 0;
}//end main

void swapRef(int &kor,int &eng){
	int temp;
	temp = kor;
	kor =eng;
	eng = temp;
	cout << "kor: " << kor << endl;
	cout << "eng: " << eng << endl;
}

void swapVar(int kor,int eng){
	int temp;
	temp = kor;
	kor =eng;
	eng = temp;
	cout << "kor: " << kor << endl;
	cout << "eng: " << eng << endl;
}

 

 


** 주소를 나열할 때, 나오는 주소의 값의 순서를 보면 메모리 영역을 알 수 있다.

 - 힙 : 영역 주소가 증가 / 스택 : 영역 주소가 감소

 

#Lvalue,Rvalue -  좌측값 / 우측값 

//assign (=)을 기준으로 좌측에 있는 값을 좌측 값, 우측에 있는 값을 우측 값이라 한다.

 - a = b; //a / b 는 좌측값 , 우측값 모두 가능하다.

 - a = a*b; //연산 부분은 우측에만 오기 때문에 "우측 값"이라고 한다.

 - int& test01();//return int& - (lvalue)좌측값 가능

    >> test01() = 300; //실제로 할당되는 것은 아니지만, 할당하는 문법이 가능하다.
 - int test02();//return int - (rvalue)좌측값 불가

//우측값만 되는 값(연산 값)에 대한 참조타입은 &를 두 번 붙인다.
 - int &&ref_sum = math + 100;

 

--예문 코드 보기--

더보기
#include <iostream>
using namespace std; 

int& test01();//return int& - (lvalue)좌측값 가능
int test02();//return int - (rvalue)좌측값 불가

int main(int argc, char **argv)
{
	cout << "-----------------" << endl;
	
	int a = 100,b=200;
	a = b; //a / b 는 좌측값 , 우측값 모두 가능하다.
	b = a;
	a = a*b; //연산 부분은 우측에만 오기 때문에 "우측 값"이라고 한다.
	
	int *p = &a;
	*p = 1000;
	
	test01() = 300;//실제로 할당되는 것은 아니지만, 할당하는 문법이 가능하다.
	cout << test01() << endl;
	cout << "-----------------" << endl;
	
	int math = 0;
	int sum = math + 100;
	//int &ref_sum = math;
	int &&ref_sum = math + 100;//우측값만 되는 값(연산 값)에 대한 참조타입은 &를 두 번 붙인다.
	cout << "sum: " << sum << endl;
	cout << "ref_sum: " << ref_sum << endl;
	
	return 0;
}

int& test01(){
	int su = 2000;
	int &ref_su = su;
	return ref_su;
}
//int test02();

 

 


 

#auto - 타입 추론 (JS의 let과 유사) 

//타입추론은 11버젼부터 가능하다.

 - auto c2 = 'B'; //char 

 - auto su2 = 100; =  auto math{99}; //int

 - auto name2 = "kim"; //string

//참조 타입의 변수의 값도 넣을 수 있다. 단, 동일 주소를 할당 받지는 않는다.

 - auto autoSu = ref_su1;

 - autoSu =99;//동일 주소를 받는게 아니기 때문에 다른 값에 영향을 미치지 않는다.
 - ref_su1 = 99;//값 할당 이후에는 별도의 값으로 auotSu에 영향을 미치지 않는다.

//단일 타입의 배열 생성도 가능하다. (auto로는 타입을 섞어서 초기화 할 수 없다.)
 - 값을 넣는 것은 동일하지만, 값에 접근하는(꺼내쓰는) 방법이 다르다.

 - sus[i] // error - 인덱스로 접근 안됨.

 - for(auto i=sus.begin();i!=sus.end();i++){//sus.begin() >> 첫번째 주소값 반환 >> i가 포인터 변수가 된다.

 - cout << i << " " << *i << endl; //값을 꺼내 올 때, 포인터 변수 필요

//함수 파라메터로 사용 불가
 - void test01(auto a); //error

 - 함수 리턴문에 auto 선언은 가능하나, 사용시 컴파일 오류가 발생하며, 대안은 decltype, template,lambda가 있다.
//구조체 혹은 클래스의 속성으로 사용불가.

 

--예문 코드 보기--

더보기
#include <iostream>
using namespace std; 

//함수 파라메터로 사용 불가
//void test01(auto a); //error
//함수 리턴문에 auto 선언은 가능하나, 사용시 컴파일 오류가 발생하며, 대안은 decltype, template,lambda가 있다.
/*
auto test02(){
	auto x = 100;
	return x;
}*/

//구조체 혹은 클래스의 속성으로 사용불가.
struct Test1{
	//auto a; //error
};
class Test2{
	//auto a; //error
};

int main(int argc, char **argv)
{
	cout << "Hello" << endl;
	cout << "-----------------" << endl;
	
	//type deduction : C++ 11
	char c1 = 'A';
	auto c2 = 'B';
	cout << "c1: " << c1 << endl;
	cout << "c2: " << c2 << endl;
	
	int su1 = 10;
	auto su2 = 100;
	cout << "su1: " << su1 << endl;
	cout << "su2: " << su2 << endl;
	
	string name1 = "lee";
	auto name2 = "kim";
	cout << "name1: " << name1 << endl;
	cout << "name2: " << name2 << endl;
	
	int su = 10;
	int &ref_su1 = su;
	auto autoSu = ref_su1;//참조 타입의 변수의 값도 넣을 수 있다. 단, 동일 주소를 할당 받지는 않는다.
	cout << "su: " << su << endl;
	cout << "ref_su1: " << ref_su1 << endl;
	cout << "autoSu: " << autoSu << endl;
	
	//autoSu =99;//동일 주소를 받는게 아니기 때문에 다른 값에 영향을 미치지 않는다.
	ref_su1 = 99;//값 할당 이후에는 별도의 값으로 auotSu에 영향을 미치지 않는다.
	cout << "su: " << su << endl;
	cout << "ref_su1: " << ref_su1 << endl;
	cout << "autoSu: " << autoSu << endl;
	
	
	cout << "-----------------" << endl;
	int kor(10);
	int eng{100};
	cout << "kor: " << kor << " " << "eng: " << eng <<endl;
	
	auto math{99};
	cout << "math: " << math <<endl;
	
	
	cout << "-----------------" << endl;
	//단일 타입의 배열 생성도 가능하다. (auto로는 타입을 섞어서 초기화 할 수 없다.)
	//값을 넣는 것은 동일하지만, 값에 접근하는(꺼내쓰는) 방법이 다르다.
	auto sus = {11,22,33};
	cout << "sus.size(): " << sus.size() << endl;
	//sus.size() loop 안됨.
	for(auto i=sus.begin();i!=sus.end();i++){//sus.begin() >> 첫번째 주소값 반환 >> i가 포인터 변수가 된다.
		//sus[i] // error - 인덱스로 접근 안됨.
		cout << i << " " << *i << endl;
	}
	
	auto ds = {11.11,22.22,33.33};
	
	//auto ds2 = {11,22.22,33.33}; //error - auto로는 타입을 섞어서 초기화 할 수 없다.
	
	cout << "-----------------" << endl;	
	
	return 0;
}//end main ()

 

 


 

#const - 상수 처리 

//1. 일반적인 상수 처리 const int su = 20;
 - su = 100;//read only error
//2. const int *pt_kor : 주소 변경 가능 / 값 변경 불가
 - const int* pt_kor = &kor; 
 - *pt_kor = 100; //read only error

//3. int* const pt_kor : 값 변경 가능, 주소 변경 불가
 - *pt_kor2 = 100; //주소를 못바꾸고 값을 바꿀수 있게 된다.
 - pt_kor2 = &eng2; //read only error 주소 변경 불가
//4. int* const pt_kor : 값 변경 불가, 주소 변경 불가
 - *pt_kor3 = 1000; //read only error 값 변경 불가
 - pt_kor3 = &eng3; //read only error 주소 변경 불가

 

--예문 코드 보기--

더보기
#include <iostream>
using namespace std; 

int main(int argc, char **argv)
{
	cout << "Hello" << endl;
	cout << "-----------------" << endl;
	
	const int su = 20;
	//su = 100;//read only error
	cout << "su: " << su << endl;
	
	cout << "-----------------" << endl;	
	//2. const int *pt_kor : 주소 변경 가능 / 값 변경 불가
	int kor = 99;
	int eng = 88;
	cout << "*kor: " << kor << endl;
	
	const int* pt_kor = &kor;
	
	//*pt_kor = 100; //read only error
	pt_kor = &eng; //값을 못 바꾸고, 주소는 변경이 가능하다.
	cout << "*kor: " << kor << endl;
	cout << "*pt_kor: " << *pt_kor << endl;
	
	cout << "-----------------" << endl;	
	//3. int* const pt_kor : 값 변경 가능, 주소 변경 불가
	int kor2 = 999;
	int eng2 = 888;
	cout << "kor2: " << kor2 << endl;
	
	int* const pt_kor2 = &kor2;
	
	*pt_kor2 = 100; //주소를 못바꾸고 값을 바꿀수 있게 된다.
	//pt_kor2 = &eng2; //read only error 주소 변경 불가
	cout << "kor2: " << kor2 << endl;
	cout << "*pt_kor2: " << *pt_kor2 << endl;
	
	cout << "-----------------" << endl;	
	//4. int* const pt_kor : 값 변경 불가, 주소 변경 불가
	int kor3 = 9999;
	int eng3 = 8888;
	cout << "*kor3: " << kor3 << endl;
	
	const int* const pt_kor3 = &kor3;
	//*pt_kor3 = 1000; //read only error 값 변경 불가
	//pt_kor3 = &eng3; //read only error 주소 변경 불가
	cout << "*kor3: " << kor3 << endl;
	cout << "*pt_kor3: " << *pt_kor3 << endl;
	
	return 0;
}