반응형
배열 기초 array
#include <iostream>
using namespace std;
#define D_NUM_STUDENTS 100000
struct Rectangle
{
int length;
int width;
};
enum StudentName
{
JACKJACK, // = 0
DASH, // = 1
VIOLET, // = 2
NUM_STUDENTS, // = 3
};
int main()
{
/*
int student1_score; // jack jack
int student2_score; // dash
int student3_score; // violet
*/
int one_student_score; // 1 variable
int student_scores[5]; // 5 int
cout << sizeof(one_student_score) << endl; // 4
cout << sizeof(student_scores) << endl; // 20
one_student_score = 100;
student_scores[0] = 100; // 1st element, 0:index
student_scores[1] = 80; // 2nd element
student_scores[2] = 90; // 3rd element
student_scores[3] = 50; // 4th element
student_scores[4] = 0; // 5th element
//student_scores[5] = 30; // 6th element? runtime error!
// 집주인에게 허락받지 않고 옆집을 사용해 버린 상황
cout << student_scores[0] << endl;
cout << student_scores[1] << endl;
cout << student_scores[2] << endl;
cout << student_scores[3] << endl;
cout << student_scores[4] << endl;
//cout << student_scores[5] << endl;
// 평범한 변수처럼 사용 가능함
cout << (student_scores[0] + student_scores[1]) / 2.0 << endl;
// 구조체 배열
Rectangle rect_arr[10];
cout << sizeof(Rectangle) << endl;
cout << sizeof(rect_arr) << endl;
rect_arr[0].length = 1;
rect_arr[0].width = 2;
// 배열 초기화
int my_array[5] = { 1, 2, 3 }; // 넣지 않으면 알아서 초기화
int my_array2[] = { 1, 2, 3, 4, 5 };
int my_array3[]{ 1, 2, 3, 4, 5 }; // C++ 11부터 가능
// enum 사용 가능
int students_scores[NUM_STUDENTS];
students_scores[JACKJACK] = 0;
students_scores[DASH] = 100;
int num_students = 0;
cin >> num_students;
//int students_scores2[num_students]; error!!
// cin으로 입력받는다는 것은 runtime에 값이 정해진다는 뜻임
// 사이즈가 고정된 배열의 사이즈는 compile-time에 고정되어야 함!!
// => C style: #define D_NUM_STUDENTS 100000(큰 수)
// 동적 할당을 이용하면 되기 때문에 권장하지 않음
// const 변수로 사이즈 설정은 가능
const int num_students2 = 10;
int students_scores3[num_students2];
return 0;
}
#include <iostream>
using namespace std;
void doSomething(int students_scores[20]) // == int students_score[], 포인터로 받아서 괄호 안 상관없음
{
// array를 함수의 parameter로 넣어 줄 수 있음
cout << (int)&students_scores << endl; // 포인터 변수의 주소값
cout << (int)&students_scores[0] << endl; // 포인터 변수에 저장되어 있는 값(원래 배열)
cout << students_scores[0] << endl;
cout << students_scores[1] << endl;
cout << students_scores[2] << endl;
cout << "Size in doSomething : " << sizeof(students_scores) << endl; // 포인터의 size
}
int main()
{
const int num_students = 20;
//cin >> num_students;
int students_scores[num_students] = {1, 2, 3, 4, 5};
cout << (int)&students_scores << endl; //1832, 첫 번째 방 주소
cout << (int)&students_scores[0] << endl; //1832
cout << (int)&students_scores[1] << endl; //1836
cout << (int)&students_scores[2] << endl; //1840
cout << (int)&students_scores[3] << endl; //1844
cout << sizeof(students_scores) << endl; // 80
cout << endl;
// ~함수와 메인 함수에서의 배열 주소가 다르게 찍히는 이유~
// 배열은 이름 자체가 내부적으로 주소로 사용이 됨, &를 붙이지 않아도 주소를 얻을 수 있음
// 함수의 매개변수로 받은 것(int students_scores[20])은 배열이 아니라 포인터!
// 배열을 받을 때 사용을 할 것이라고 코딩을 할 수 있는 것뿐, 컴파일러 내부에서는 포인터로 처리함
// 배열의 모든 원소를 복사해서 가져오는 것이 아닌, 배열의 첫 번째 주소값만 넘어간다는 것임
cout << (int)&students_scores << endl;
cout << students_scores[0] << endl;
cout << students_scores[1] << endl;
cout << students_scores[2] << endl;
cout << "Size in main : " << sizeof(students_scores) << endl;
doSomething(students_scores);
return 0;
}
배열과 반복문
#include <iostream>
using namespace std;
int main()
{
//const int num_students = 5;
/*
int score0 = 84;
int score1 = 92;
int score2 = 76;
int score3 = 81;
int score4 = 56;
int total_score = score0 + score1 + score2 + score3 + score4;
double avg_score = static_cast<double>(total_score) / num_students;
//Note: double(total_score) / num_students != double(total_score / num_students);
*/
int scores[] = { 84, 92, 76, 81, 56 };
// 배열이 함수 parameter로 넘어갔을 때, 함수에서 이렇게 연산하면 포인터의 사이즈를 계산해 버릴 수 있으니 주의!!
// 배열을 보낼 때는 elements 개수를 같이 넘기기
const int num_students = sizeof(scores) / sizeof(int);
int max_score = 0;
int min_score = numeric_limits<int>::max();
int total_score = 0;
for (int i = 0; i < num_students; i++)
{
total_score += scores[i];
if (scores[i] > max_score)
max_score = scores[i];
//max_score = (max_score < scores[i]) ? scores[i] : max_score;
if (scores[i] < min_score)
min_score = scores[i];
//min_score = (min_score > scores[i]) ? scores[i] : min_score;
}
double avg_score = static_cast<double>(total_score) / num_students;
cout << max_score << endl;
cout << min_score << endl;
return 0;
}
배열과 선택 정렬 selection sort
정렬(sorting): 순서를 맞춰 주는 것
#include <iostream>
using namespace std;
void printArray(const int array[], int length)
{
for (int index = 0; index < length; index++)
cout << array[index] << " ";
cout << endl;
}
int main()
{
/* value index
3 5 2 1 4 1 3
1 5 2 3 4 2 2
1 2 5 3 4 3 3
1 2 3 5 4 4 4
1 2 3 4 5
*/
const int length = 5;
int array[length] = { 3,5,2,1,4 };
printArray(array, 5);
// swap
//int temp = array[0];
//array[0] = array[1];
//array[1] = temp;
//
//printArray(array, 5);
// std::swap(...)
// 내가 구현한 선택 정렬
for (int i = 0; i < length - 1; i++)
{
int value = array[i];
int index = i;
for (int j = i + 1; j < length; j++)
{
if (array[j] < value)
{
value = array[j];
index = j;
}
}
array[index] = array[i];
array[i] = value;
printArray(array, length);
}
cout << endl;
int array2[length] = { 8,1,9,3,5 };
printArray(array2, length);
for (int startIndex = 0; startIndex < length - 1; startIndex++)
{
int smallestIndex = startIndex;
for (int currentIndex = startIndex + 1; currentIndex < length; currentIndex++)
{
if (array2[smallestIndex] > array2[currentIndex])
{
smallestIndex = currentIndex;
}
}
// swap two values in the array
// std::swap(array2[smallestIndex], array[startIndex]);
{
int temp = array2[smallestIndex];
array2[smallestIndex] = array2[startIndex];
array2[startIndex] = temp;
}
printArray(array2, length);
}
return 0;
}
정적 다차원 배열
메모리는 일차원적 구조
#include <iostream>
using namespace std;
int main()
{
const int num_rows = 3;
const int num_columns = 5;
for (int row = 0; row < num_rows; row++)
{
for (int col = 0; col < num_columns; col++)
{
cout << '[' << row << ']' << '[' << col << ']' << '\t';
}
cout << endl;
}
cout << endl;
int array[num_rows][num_columns] = // row-major <-> column-major
{
{1,2,3,4,5}, // row 0
{6,7,8,9,10}, // row 1
{11,12,13,14,15} // row 2
};
//array[0][0] = 1;
for (int row = 0; row < num_rows; row++)
{
for (int col = 0; col < num_columns; col++)
{
cout << array[row][col] << '\t';
}
cout << endl;
}
cout << endl;
// 주소 찍어 보면 4씩 차이남
for (int row = 0; row < num_rows; row++)
{
for (int col = 0; col < num_columns; col++)
{
cout << (int)&array[row][col] << '\t';
}
cout << endl;
}
// num_rows만 생략 가능! num_columns는 생략 불가능
int array2[][num_columns] =
{
{1,2}, // 나머지 0으로 채움
{6,7,8,9,10},
{11,12,13,14,15}
};
int array3[num_rows][num_columns] = { 0 };
int array4[5][4][3];
return 0;
}
C언어 스타일의 배열 문자열
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char myString[] = "string"; // 마지막 자리에 null character가 있음! '\0'
for (int i = 0; i < 7; i++)
cout << (int)myString[i] << endl;
cout << sizeof(myString) / sizeof(myString[0]) << endl; // array size: 7
cout << endl;
// 입력받기
char myString2[255];
//cin >> myString2;
cin.getline(myString2, 255); // 공백 포함해서 입력받기
//myString2[0] = 'A';
//cout << myString2 << endl;
// char로 된 문자열을 출력할 경우, NULL(\0)이 나오기 전까지 출력함
//myString2[4] = '\0';
//cout << myString2 << endl;
int ix = 0;
// while문으로 출력하기
while (true)
{
if (myString2[ix] == '\0') break;
cout << myString2[ix] << " " << (int)&myString2[ix] << endl;
ix++;
}
cout << endl;
// cstring 안에 정의되어 있는 함수들
char source[] = "Copy this!";
char dest[50];
strcpy_s(dest, 50, source);
//cout << source << endl;
//cout << dest << endl;
//strcat() 문자열 뒤에 붙여 주기
strcat_s(dest, source);
cout << "source: " << source << endl;
cout << "dest: " << dest << endl;
//strcmp() 두 문자열이 동일한지 비교하기
//같으면 0 return!! 조건문 사용시 조심
cout << strcmp(source, dest) << endl;
if (strcmp(source, dest) == 0)
{
}
return 0;
}
//strcat와 동일하게 작동하는 함수 구현
//strcmp와 동일하게 작동하는 함수 구현
#include <iostream>
using namespace std;
void myStrcat(char *ori, int length, const char *cop)
{
int idx = 0;
while (true)
{
ori[length + idx] = cop[idx];
if (cop[idx++] == '\0')
break;
}
}
int myStrcmp(char *c1, char *c2)
{
int idx = 0;
while (c1[idx] != '\0' || c2[idx] != '\0')
{
if (c1[idx] > c2[idx])
{
return 1;
}
else if (c1[idx] < c2[idx])
{
return -1;
}
idx++;
}
return 0;
}
int myStrlen(char *ori)
{
int idx = 0;
while (true)
{
if (ori[idx] == '\0')
return idx;
idx++;
}
}
int main()
{
const int MAX = 100;
char a[MAX] = "Hello ";
char b[MAX] = "World!";
int length = myStrlen(a);
cout << length << endl;
myStrcat(a, length, b);
length = myStrlen(a);
for (int i = 0; i < length; i++)
{
cout << a[i];
}
cout << endl;
char c[MAX] = "aaaazz";
char d[MAX] = "aaaazz";
cout << (myStrcmp(c, d) == 0 ? "두 문자열은 같습니다." : "두 문자열은 다릅니다.") << endl;
return 0;
}
포인터의 기본적인 사용법
지역 변수: '스택'
동적 할당 메모리: '힙'
필요한 데이터가 저장되어 있는 주소를 사용하여 직접 접근하여 가져온다.
#include <iostream>
using namespace std;
int* doSomething(int* ptr_a)
{
return nullptr;
}
struct Something
{
int a, b, c, d; // 4 * 4bytes
};
int main()
{
int x = 5;
cout << x << endl;
cout << &x << endl; // &: address-of operator
cout << (int)&x << endl;
// de-reference operator (*)
// reference: 간접적으로 참고하는 개념
// de-reference: 포인터가 데이터의 주소를 간접적으로 가리키고 있는 것에 대하여, 그곳에 뭐가 있는지 직접 접근하겠다는 의미
cout << *(&x) << endl; // == x
cout << endl;
// pointer: 메모리 주소를 담는 변수
typedef int* pint;
int *ptr_x = &x, *ptr_y = &x;
//int *ptr_x = &x, ptr_y = &x; // error!! ptr_y에도 *을 붙여야 함
//pint ptr_x = &x, ptr_y = &x; // 가능하지만 typedef보다는 직접 선언하기
cout << ptr_x << endl; // 데이터의 주소
cout << *ptr_x << endl; // 데이터의 주소에 있는 내용(데이터)
cout << endl;
// array를 parameter로 넣으면 전부 복사됨... => 포인터로 첫 번째 주소와 데이터 개수만 알려 준다면 해결 가능
double d = 123.0;
//int *ptr_i = &d; // error!
double *ptr_d = &d;
cout << ptr_d << endl;
cout << *ptr_d << endl;
cout << typeid(ptr_x).name() << endl; // 출력: int *, gcc에서는 Pi 출력
// 포인터 자체의 사이즈는 고정! 주소는 그냥 주소임!
// 단, 포인터에도 타입이 있는 이유는 de-referencing을 위해
// 64비트에서는 주소가 더 긺
cout << sizeof(x) << endl; // 출력: 4
cout << sizeof(d) << endl; // 출력: 8
cout << sizeof(&x) << " " << sizeof(ptr_x) << endl; // 출력: 4 4
cout << sizeof(&d) << " " << sizeof(ptr_d) << endl; // 출력: 4 4
cout << endl;
Something ss;
Something *ptr_s;
cout << sizeof(Something) << endl; // 출력: 16
cout << sizeof(ptr_s) << endl; // 출력: 4
cout << endl;
// 초기화 안 된 상태에서 출력하면 엉뚱한 값임
int *ptr_a;
cout << *ptr_a << endl;
return 0;
}
널 포인터 Null Pointer
#include <iostream>
#include <cstddef>
using namespace std;
void doSomething(double *ptr)
{
// parameter는 다시 선언이 되고, 값이 복사가 되는 형식임! 따라서 다른 main()과 주소 출력!
cout << "address of pointer variable in doSomething() " << &ptr << endl;
if (ptr != nullptr)
{
// do something useful
cout << *ptr << endl;
}
else
{
// do nothing with ptr
cout << "Null ptr, do nothing" << endl;
}
}
int main()
{
double *ptr = 0; // c-style
double *ptr2 = NULL;
double *ptr3{ nullptr }; // modern C++
double d = 123.4;
doSomething(ptr);
doSomething(nullptr);
doSomething(&d);
ptr = &d;
doSomething(ptr);
cout << "address of pointer variable in main() " << &ptr << endl;
std::nullptr_t nptr; // null pointer type, parameter로 널 포인터만 받아야 하는 경우 사용
return 0;
}
포인터와 정적 배열
이후 메모리 동적 할당, 동적 배열 등을 이해할 때 중요함
#include <iostream>
using namespace std;
//void printArray (int *array) 동일함!
void printArray(int array[])
{
// parameter로 배열이 들어오는 것처럼 보이지만, 내부적으로는 포인터로 다룸
cout << sizeof(array) << endl; // 출력: 4
cout << *array << endl; // 출력: 9
*array = 100;
}
int main()
{
int array[5] = { 9,7,5,3,1 };
// array는 배열이 아니라 '포인터', 첫 번째 방의 주소를 담고 있음
cout << array[0] << " " << array[1] << endl;
cout << array << endl; // == &array[0]
cout << &array[0] << endl;
cout << *array << endl; // 출력: 9
// 문자형 포인터이기 때문에 직접 접근 시 문자형으로 출력함
char name[] = "jackjack";
cout << *name << endl; // 출력: j
int *ptr = array;
cout << ptr << endl; // == &array[0]
cout << *ptr << endl; // 출력: 9
cout << sizeof(array) << endl; // 출력: 20, 4*5
cout << sizeof(ptr) << endl; // 출력: 4, 포인터 변수의 size
printArray(array);
// printArray 함수 안에서 변경한 것을 main 함수에서도 확인 가능
// C에서는 이러한 용도로 많이 사용하였음, C++은 reference를 사용
cout << array[0] << " " << *array << endl; // 출력: 100 100
// 포인터 연산, 다음 항목 출력 가능
cout << *ptr << " " << *(ptr + 1) << endl; // 출력: 100 7
return 0;
}
#include <iostream>
using namespace std;
struct MyStruct
{
int array[5] = { 9,7,5,3,1 };
};
void doSomething(MyStruct ms)
{
cout << sizeof(ms.array) << endl; // 출력: 20
}
void doSomething(MyStruct *ms)
{
cout << sizeof((*ms).array) << endl; // 출력: 20
}
int main()
{
// array가 structure, class 안에 들어 있을 경우, 포인터로 강제 변환되지 않음
MyStruct ms;
cout << ms.array[0] << endl;
cout << sizeof(ms.array) << endl; // 출력: 20
doSomething(ms);
doSomething(&ms);
return 0;
}
포인터 연산과 배열 인덱싱
#include <iostream>
using namespace std;
int main()
{
short value = 7;
short *ptr = &value;
// 데이터 타입의 사이즈에 맞춰서 옆으로 한 칸
cout << uintptr_t(ptr - 1) << endl;
cout << uintptr_t(ptr) << endl;
cout << uintptr_t(ptr + 1) << endl;
cout << uintptr_t(ptr + 2) << endl;
int array[] = { 9,7,5,3,1 };
int *ptr2 = array;
for (int i = 0; i < 5; i++)
{
//cout << array[i] << " " << uintptr_t(&array[i]) << endl;
cout << *(ptr2 + i) << " " << uintptr_t(ptr2 + i) << endl;
}
char name[] = "Jack jack";
const int n_name = sizeof(name) / sizeof(name[0]);
char *ptr3 = name;
for (int i = 0; i < n_name; i++)
{
//cout << *(name + i);
cout << *(ptr3 + i);
}
return 0;
}
#include <iostream>
// while문과 break를 사용해서 문자열을 출력, 마지막에 널 캐릭터는 출력하지 않게끔
// 포인트 연산 사용 ++ptr
using namespace std;
void printArray(char *arr)
{
char *ptr = arr;
while (true)
{
cout << *ptr << endl;
if (*(++ptr) == '\0')
return;
}
}
int main()
{
const int MAX = 100;
char array[MAX];
cout << "문자열을 입력해 주세요." << endl;
while (true)
{
cin.getline(array, MAX);
if (!cin.fail())
break;
cin.clear();
cin.ignore(MAX, '\n');
}
printArray(array);
return 0;
}
C언어 스타일의 문자열 심볼릭 상수
#include <iostream>
using namespace std;
// return type 가능
const char* getName()
{
return "Jack Jack";
}
int main()
{
//char name[] = "Jack Jack";
//char *name = "Jack Jack"; error!! 실제로 "Jack Jack"이 담길 메모리에 대한 정보가 없음
const char *name = "Jack Jack"; // 가능
const char *name2 = getName();
const char *name3 = "Jack Jack2";
cout << uintptr_t(name) << endl;
cout << uintptr_t(name2) << endl; // 동일한 메모리 사용
cout << uintptr_t(name3) << endl; // 다른 메모리 사용
int int_arr[5] = { 1,2,3,4,5 };
char char_arr[] = "Hello, World!";
// cout에서 문자열은 특별하게 처리함! 문자의 포인터가 들어오면 문자의 배열일 가능성이 높다고 판단
cout << int_arr << endl; // 출력: 주소
cout << char_arr << endl; // 출력: Hello, World!
cout << name << endl; // 출력: Jack Jack
char c = 'Q';
// 메모리 주소가 들어가니까 문자열이라고 생각하기 때문에, null이 나올 때까지 쭉 출력함!
cout << &c << endl;
return 0;
}
메모리 동적 할당 new와 delete
static memory allocation: 전역 변수, static 변수 등 한번 만들어지면 프로그램이 끝날 때까지 계속 메모리를 갖고 있는 것
dynamic memory allocation
자동 메모리 할당: 변수, 정적 배열 등 블럭 밖으로 나가면 메모리 해제
#include <iostream>
using namespace std;
int main()
{
// 정적으로 할당하는 것들은 stack에 할당, 동적은 heap
//int array[1000000]; // error!! Stack overflow
//int var;
//var = 7;
int *ptr = new int(7); // new int: int에 맞춰서 메모리를 받아오고, 그 주소를 알려줌
// new int { 7 };
*ptr = 7;
cout << ptr << endl;
cout << *ptr << endl;
// 중요!! 할당받은 메모리를 다시 돌려 줌
// OS가 메모리를 기억하고 있기 때문에 프로그램이 종료되면 자동으로 회수함
// delete는 OS가 가져가기 전에 먼저 수동으로 반납하는 것임!
delete ptr;
ptr = NULL; // 해제 후 NULL, 0, nullptr 넣어 주기
// 삭제를 하더라도 주소는 그대로 남아 있음, 알고 있던 집으로 갔더니 다른 주소더라
cout << "After delete" << endl;
if(ptr != nullptr)
{
cout << ptr << endl;
cout << *ptr << endl;
}
// 다른 프로그램이 모두 메모리를 사용하고 있어서 할당받지 못할 때가 있음
// 프로그램이 죽지 않게 짜려면... std::nothrow => 오류를 발생시키지 않고 실행함
int *ptr2 = new (std::nothrow) int{ 7 };
if (ptr2)
{
cout << ptr2 << endl;
cout << *ptr2 << endl;
}
else
{
cout << "Could not allocate memory" << endl;
}
int *ptr3 = ptr2;
delete ptr2;
ptr2 = nullptr;
ptr3 = nullptr; // ptr3 해제하지 않고 *ptr3 접근하면 오류 발생!!
// memory leak 메모리 누수
// 1. 할당하는 메모리가 큰 경우, 작업 관리자 확인
// 2. debugger의 Diagnostic Tools 확인
// new와 delete는 OS에 다녀와야 하기 때문에 느림 => 적게 사용하는 것이 좋음
while (true)
{
int *ptr = new int;
cout << ptr << endl;
delete ptr;
}
return 0;
}
동적 할당 배열
Dynamically Allocating Arrays: run-time에 배열의 사이즈를 결정하고, 그때그때 OS에서 메모리를 받아오기 때문에 유동적으로 사용이 가능함
#include <iostream>
using namespace std;
int main()
{
int length;
cin >> length;
//int array[length];
int *array = new int[length](); // 전부 0으로 초기화
// {11, 22, 33, 44, 55, 66}; // length를 6 미만으로 할 경우 error!
array[0] = 1;
array[1] = 2;
for (int i = 0; i < length; i++)
{
cout << (uintptr_t)&array[i] << endl;
cout << array[i] << endl;
}
delete[] array;
int fixedArray[] = { 1,2,3,4,5 }; // compile-time
int *array2 = new int[3]{ 1,2,3 }; // new int[]시 빌드 실패!
// resizing, 직접적으로는 안 됨! 더 큰 메모리를 받은 다음 복사해서 옮기기
// OS에 요청을 할 수 있음(될 수도 있고, 안 될 수도 있음)
delete[] array2;
return 0;
}
포인터와 const
#include <iostream>
using namespace std;
int main()
{
const int value = 5; // 변수가 const면
const int *ptr = &value; // 포인터도 const
//*ptr = 6; error!
//value = 6; error!
cout << *ptr << endl; // 출력은 문제없음
int value2 = 5;
const int *ptr2 = &value2;
//*ptr2 = 6; error!
value2 = 6;
cout << *ptr2 << endl; // 출력은 문제없음
int v1 = 5;
const int *p = &v1; // const int *: 가리키고 있는 주소에 있는 '데이터'를 바꾸지 않겠다!
//*p = 10; error!
int v2 = 6;
p = &v2; // 가능!
int v3 = 5;
int *const p2 = &v3; // int *const: 가리키고 있는 '메모리 주소'를 바꾸지 않겠다!
*p2 = 10; // 가능!
int v4 = 8;
//p2 = &v4; error!
const int *const p3 = &value; // 초기화 필요
// 함수 parameter에서 종종 사용!
int a = 5;
const int *pt1 = &a;
int *const pt2 = &a;
const int *const pt3 = &a;
return 0;
}
참조 변수 reference variable
변수의 별명처럼 사용할 수 있음
#include <iostream>
using namespace std;
//void doSomething(int &n)
void doSomething(const int &n) // 값 변경 불가
{
//n = 10;
cout << "In doSomething " << n << endl;
cout << "In doSomething " << &n << endl;
}
int main()
{
int value = 5;
const int y = 8;
int *ptr = nullptr;
ptr = &value;
int &ref = value; // 참조, ref = value처럼 작동함
//int &r; error! reference는 반드시 초기화되어야 함
//int &r = 104; error! 리터럴은 메모리 주소가 없음
//int &r = y; error!
const int &r = y; // const는 const로 선언
cout << ref << endl;
ref = 10;
cout << value << " " << ref << endl; // 출력: 10 10
cout << &value << endl;
cout << &ref << endl; // value와 동일한 주소
cout << ptr << endl;
cout << &ptr << endl;
int value1 = 5;
int value2 = 10;
int &ref1 = value1;
cout << ref1 << endl;
ref1 = value2;
cout << ref1 << endl;
int n = 5;
cout << n << endl;
cout << &n << endl;
// 포인터는 복사해서 넣어 주는 것, 레퍼런스를 쓰게 되면 아예 변수 자체가 넘어감
// 주소조차도 복사할 필요가 없기 때문에 효율이 더 높음
doSomething(n);
cout << n << endl;
return 0;
}
#include <iostream>
using namespace std;
void printElements(const int(&arr)[5]) // 이 경우, [5] 필수
{
for (int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
struct Something
{
int v1;
float v2;
};
struct Other
{
Something st;
};
int main()
{
const int length = 5;
int arr[length] = { 1,2,3,4,5 };
printElements(arr);
Other ot;
//ot.st.v1 = 1;
int &v1 = ot.st.v1;
v1 = 1;
int value = 5;
// 기능상 동일함
int *const ptr = &value;
int &ref = value;
*ptr = 10;
ref = 10;
return 0;
}
참조와 const
#include <iostream>
using namespace std;
void doSomething(const int& x) // 장점: 복사X
{
cout << x << endl;
}
int main()
{
int a = 1;
doSomething(a);
doSomething(1); // parameter가 const reference라면 가능!
doSomething(a + 3);
doSomething(3 * 4);
return 0;
}
포인터와 참조의 멤버 선택
#include <iostream>
using namespace std;
struct Person
{
int age;
double weight;
};
int main()
{
Person person;
person.age = 5; // member selection operator
person.weight = 30;
Person &ref = person;
ref.age = 15;
Person *ptr = &person;
ptr->age = 25;
(*ptr).age = 20;
Person &ref2 = *ptr;
ref2.age = 45;
cout << &person << endl;
cout << &ref2 << endl; // 원본과 동일한 주소
return 0;
}
C++11 For-each 반복문
#include <iostream>
#include <limits>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int fibonacci[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
// change array values? => 실패
for (int number : fibonacci)
number = 10;
for (auto &number : fibonacci) // reference
number *= 10;
// output
for (const auto &number : fibonacci)
cout << number << " ";
cout << endl;
// 가장 큰 숫자 찾기
int max_number = numeric_limits<int>::lowest();
for (const auto &n : fibonacci)
max_number = max(max_number, n);
cout << max_number << endl;
// 동적 할당 array는 for-each 사용 불가능 => vector 사용!
// 동적 할당 배열을 아주 편하게 사용할 수 있게 std에 들어 있음
vector<int> fibonacci = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
return 0;
}
보이드 포인터
#include <iostream>
using namespace std;
enum Type
{
INT,
FLOAT,
CHAR
};
int main()
{
// void pointer, generic(포괄적) pointer
int i = 5;
float f = 3.0;
char c = 'a';
void *ptr = nullptr;
// 주소 넣는 것은 문제 없음! 단, 그렇기 때문에 어떤 타입인지 알 수가 없어짐
ptr = &i;
ptr = &f;
//ptr = &c;
int *ptr_i = &i;
cout << ptr_i << endl;
cout << ptr_i + 1 << endl;
cout << &f << " " << ptr << endl; // '주소' 출력 가능
//cout << *ptr << endl; // error! 주소에 값이 있는 건 알겠지만, 어떤 형인지 알 수 없음!
cout << *static_cast<float*>(ptr) << endl;
//cout << ptr + 1 << endl; // error! 대체 몇 바이트를 더해야 하는지 알 수 없음!
// void pointer를 많이 사용하진 않겠지만... 포인터를 이해하는 데 도움이 됨
Type type = FLOAT;
if (type == FLOAT)
cout << *static_cast<float*>(ptr) << endl;
else if(type == INT)
cout << *static_cast<int*>(ptr) << endl;
return 0;
}
다중 포인터와 동적 다차원 배열
#include <iostream>
using namespace std;
int main()
{
int *ptr = nullptr;
int **ptrptr = nullptr; // 이중 포인터, 포인터에 대한 포인터, 원래 데이터 타입은 integer
int value = 5;
ptr = &value;
ptrptr = &ptr;
cout << ptr << " " << *ptr << " " << &ptr << endl;
cout << ptrptr << " " << *ptrptr << " " << &ptrptr << endl;
cout << **ptrptr << endl;
cout << endl;
const int row = 3;
const int col = 5;
const int s2da[][5] =
{
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}
};
/*
int *r1 = new int[col] { 1, 2, 3, 4, 5 };
int *r2 = new int[col] { 6, 7, 8, 9, 10 };
int *r3 = new int[col] { 11, 12, 13, 14, 15 };
int **rows = new int*[row] {r1, r2, r3};
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++)
cout << rows[r][c] << "\t";
cout << endl;
}
delete[] r1;
delete[] r2;
delete[] r3;
delete[] rows;
*/
int **matrix = new int*[row];
for (int r = 0; r < row; r++)
matrix[r] = new int[col];
for (int r = 0; r < row; r++)
for (int c = 0; c < col; c++)
matrix[r][c] = s2da[r][c];
// print all elements
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++)
cout << matrix[r][c] << "\t";
cout << endl;
}
// delete
for (int r = 0; r < row; r++)
delete[] matrix[r];
delete matrix;
cout << endl;
int *matrix2 = new int[row*col];
for (int r = 0; r < row; r++)
for (int c = 0; c < col; c++)
matrix2[c + col * r] = s2da[r][c];
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++)
cout << matrix2[c + col * r] << "\t";
cout << endl;
}
delete[] matrix2;
return 0;
}
std::array 소개
#include <iostream>
#include <array>
#include <algorithm>
using namespace std;
void printLength(const array<int, 5>& my_arr)
{
// 똑같이 작동 가능하나, array 또한 복사되어 작동함! (& 이용)
cout << my_arr.size() << endl;
}
int main()
{
//int array[5] = { 1, 2, 3, 4, 5 };
array<int, 5> my_arr = { 1, 2, 3, 4, 5 }; // 선언 시, 숫자가 꼭 들어가야 함
my_arr = { 0, 1, 2 }; // 가능
cout << my_arr[0] << endl;
cout << my_arr.at(0) << endl; // 똑같이 출력하나, 검색 후 문제 발생시 예외 처리!
cout << my_arr.size() << endl;
printLength(my_arr);
cout << endl;
array<int, 5> arr2 = { 1,21,3,40,5 };
for (auto &element : arr2)
cout << element << " ";
cout << endl;
sort(arr2.begin(), arr2.end());
for (auto &element : arr2)
cout << element << " ";
cout << endl;
sort(arr2.rbegin(), arr2.rend());
for (auto &element : arr2)
cout << element << " ";
cout << endl;
return 0;
}
std::vector 소개
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//std::array<int, 5> array;
std::vector<int> array;
std::vector<int> array2 = { 1,2,3,4,5 };
std::vector<int> array3 = { 1,2,3 };
std::vector<int> array4 { 1,2,3 };
cout << array2.size() << endl;
cout << array3.size() << endl;
cout << array4.size() << endl;
array2.resize(10); // resize 가능
for (auto &itr : array2)
cout << itr;
cout << endl;
cout << array2[1] << endl;
cout << array2.at(1) << endl;
cout << array2.size() << endl; // size
int *my_arr = new int[5];
delete[] my_arr; // 꼭 지워야 한다는 부담이 있음
// vector는 블럭을 나가면 사라짐!! 아주 큰 장점
return 0;
}
해당 포스트는 '홍정모의 따라하며 배우는 C++' 강의를 수강하며 개인 백업용으로 메모하였습니다.
반응형