배열, 포인터, 참조변수

이영준·2022년 3월 30일
0
post-thumbnail

🔑배열

배열은 하나의 식별자에 인덱스를 추가하여 개별적으로 참조할 수 있는 인접한 메모리 위치에 배치된 동일한 유형의 일련의 요소입니다.

type name[elements];
type name[]={constructor1,2,,,,,}

ex)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>

using namespace std;;

class Unit {
private: 
	int x, y;
public:
	Unit(int a) {
		x = a; y = a;
	}

	void Print() {
		cout << x << "," << y << "\n";
	}
};

int main() {
	Unit aUnit[2] = { Unit(1),Unit(2) };

	for (int i = 0; i < 2; i++) {
		cout << "aUnit[" << i << "]=";
		aUnit[1].Print();
	}

	return 0;
}

🔑포인터

• 포인터는 컴퓨터 메모리에 저장된 다른 변수(또는 객체)의 주소를 직접 참조(또는 "포인트")하는 변수입니다.
• 기본 데이터 형식에는 '' 연산자를 사용합니다.
• 개체 포인터는 '->' 및 '
' 연산자를 사용하여 개체에 액세스할 수 있습니다.

ex)

#include <iostream>

using namespace std;

class Unit {
private:
	int x, y;

public:
	Unit(int a, int b) {
		x = a; y = b;
	}

	void Print() {
		cout << x << "," << y << "\n";
	}
};

int main() {
	Unit aUnit[2] = { Unit(1,2),Unit(3,4) };
	int i;
	Unit* pUnit = aUnit;//배열은 첫번째 주소의 주솟값만 담고 있으므로 포인터로 쓸 수 있음

	cout << "Using '->' operator \n";
	for (i = 0; i < 2; i++) {
		pUnit->Print();
		pUnit++;
	}
	
	cout<< "자바스러운 방법 \n";
	for(i=0; i<2; i++){
	    aUnit[i].Print();
	}

	pUnit = aUnit;

	cout << "Using '.' operator \n";
	for (i = 0; i < 2; i++) {
		(*pUnit).Print();
		pUnit++;
	}
}

결과:
Using '->' operator
1,2
3,4
자바스러운 방법
1,2
3,4
Using '.' operator
1,2
3,4

같은 뜻의 구문을 위처럼 다른 방식으로 쓸 수 있다

this 포인터

• C++의 모든 오브젝트는 this 포인터라고 불리는 중요한 포인터를 통해 자신의 주소에 액세스할 수 있습니다.
• 이 포인터는 모든 멤버 함수에 대한 암묵적인 파라미터입니다.

this 포인터 퀴즈

#include <iostream>


using namespace std;

class Unit {
private:
	int x, y;

public:
	Unit* p;

	Unit(int x, int y, Unit* p) : x(x), y(y), p(p) {}


	void Print() {

	cout << this->x << ", " << this->y << endl;
	if (!p) return;
	this->p->Print();


	}
};

int main() {
	Unit c(5, 6, NULL);
	Unit b(3, 4, &c);
	Unit a(1, 2, &b);

	cout << "[print a]" << endl; a.Print();
	cout << "[Print b]" << endl; b.Print();
	cout << "[Print c]" << endl; c.Print();

	return 0;

}

결과:
[print a]
1, 2
3, 4
5, 6
[Print b]
3, 4
5, 6
[Print c]
5, 6

a.print()의 this는 &a,
&a->p는 &b,
&b->print()는 곧 b.print()를 뜻하게 되므로 연쇄적으로 출력이 된다.

🔑New, Delete

동적 메모리 할당(<-> 정적 메모리 할당)
• 메모리는 실행 시간 중에 "즉시" 할당
• 컴파일러가 정확한 용량이나 항목 수를 미리 알 필요가 없습니다.
• new 연산자는 해당 메모리를 사용하여 객체를 만든 다음 할당된 메모리의 주소가 포함된 포인터를 반환합니다.

출처: https://boycoding.tistory.com/204 [소년코딩]

data_type data = new data_type;
data_type
data = new data_type[elements];
class_type object = new class_type();
class_type
objectA = new class_type[elements] class_type *objectB = new class_type[elements]{class_type(),…, class_type()};
delete data;
delete[ ] dataA;
delete object;
delete[] objectA;
delete[] objectB;

int plnteger = new int;
int
plntegerA = new int[10];
Unit pUnit = new Unit(1,2);
Unit
pUnitA = new Unit[2];
Unit* pUnitB = new Unit[2]{Unit(1,2),Unit(3,4)};
delete plnteger;
delete[ ] plntegerA;
delete pUnit;
delete[ ] pUnitA;
delete[ ] pUnitB;

ex1)

#include <iostream>

using namespace std;
class Unit {
	int x, y;
public:
	Unit(int x, int y) : x(x), y(y) {}
	void Print() {
		cout << x << "," << y << "\n";
	}
};



	
int main() {
	int* pInteger = NULL;
	pInteger = new int;

	if (!pInteger) {
		cout << "Allocation Fail\n";
		return -1;
	}

	*pInteger = 777;
	cout << "pInteger = " << pInteger << " *pInteger = " << *pInteger << "\n";

	delete pInteger;

	Unit* pUnit = new Unit(1, 2);
	pUnit->Print();
	delete pUnit;

}

결과:
pInteger = 000001B0AD4360C0 *pInteger = 777
1,2

New, Delete 퀴즈

#include <iostream>

using namespace std;
class Unit {
	int x, y;
public:
	Unit() : x(1), y(1) {}
	Unit(int x, int y) : x(x), y(y) {}
	void Print() {
		cout << x << "," << y << "\n";
	}
};




int main() {

	Unit* pUnit = new Unit[2];

	pUnit[0] = Unit(1, 2);
	pUnit[1] = Unit(3, 4);
	for (int i = 0; i < 2; i++) {
		pUnit[i].Print();
	}



}

🔑레퍼런스(참조) 변수

• 참조를 통해 프로그래머는 변수에 저장된 원래 데이터를 읽거나 수정하기 위해 사용할 수 있는 변수의 두 번째 이름을 만들 수 있습니다.
• 참조가 생성되면 나중에 다른 개체를 참조하도록 만들 수 없습니다.

type &name;
int A=5;
int &rA = A;

즉, 참조형 변수는 참조하는 값과 동일하게 작동한다. &가 주소를 뜻하는 것이 아니다!

call-by-value, call-by-reference

call-by-value와 call-by-reference를 잘 설명해주신 글이 있다.

#include <iostream>
using namespace std;

void swap(int x, int y) {
	int t;
	t = x;
	x = y;
	y = t;
}

void pointerSwap(int *x, int *y) {
	int t;
	t = *x;
	*x =*y;
	*y = t;
}

int main() {
	int i = 4;
	int j = 7;
	cout << "i: " << i << " j : "<< j << endl;
	swap(i, j);
	cout << "i: " << i << " j : " << j << endl;

	cout << "i: " << i << " j : " << j << endl;
	pointerSwap(&i, &j);
	cout << "i: " << i << " j : " << j << endl;

}

결과:
i: 4 j : 7
i: 4 j : 7
i: 4 j : 7
i: 7 j : 4

단순 value를 참조한 swap은 새로운 메모리를 할당받아 4,7이라는 값만 가져오는 것이므로 swap함수 내에서는 x,y가 바뀌었으나 실제 main에서는 바뀌지 않았다.

반면 pointerSwap의 경우에는 x,y의 주솟값을 받아와 주솟값에 해당하는 값을 바꾸므로 main 함수에 적용이 된다.

레퍼런스를 이용한 swap

void referenceSwap(int& x, int& y) {
	int t;
	t = x;
	x = y;
	y = t;

}

포인터로 스왑한 것과 같이 스왑된다.

🔑배열포인터 퀴즈

#include <iostream>
#include <vector>
using namespace std;

int FindMaxNumber(vector<int> argGrade) {
	int size = argGrade.size();
	int max = argGrade[0];
	int maxIndex = 0;
	for (int i = 0; i < size; i++) {
		if (argGrade[i] > max) {
			max = argGrade[i];
			maxIndex = i;
		}
	}
	return maxIndex;
}

void main() {
	vector<int> aGrade = { 90,88,85,55,47,92,87,30,89,65 };
	int maxGradeIndex = 0;

	maxGradeIndex = FindMaxNumber(aGrade);

	cout << "Best Grade = " << aGrade[maxGradeIndex] << "\n";
	cout << "StudentID= " << maxGradeIndex + 1 << "\n";
}

Vector 컨테이너를 이용하여 동적인 배열을 매개변수로 받는 함수를 작성하였다.
Vector 사용과 sizeof(arr) / sizeof(int) 가 안되는 이유

profile
컴퓨터와 교육 그사이 어딘가

0개의 댓글