using namespace std; // 네임스페이스 생략 가능, std::cin → cin std::cin >> 변수1 >> 변수2 >> ...; std::cout << "문자열" << '문자' << 변수 << ... << std::endl; // endl : 줄바꿈 // <<와 >>는 스트림이 흘러가는 방향으로 기억하자
namespace MySpace {
namespace InnerSpace {
void myFunction() { }
}
void myFunction() {
//...
}
}
MySpace::myFunction();
MySpace::InnerSpace::myFunction();
// 네임스페이스 생략 방법
// using namespace MySpace; → MySpace에 속한 모든 대상
// using MySpace::myFunction; → myFunction만 지정
// #define은 단순 치환 기능 (단, 전처리문 안에서는 치환하지 않음) #define MAX(x,y) (((x)>(y))?(x):(y)) // 매크로 함수, 비슷한 기능의 std::max가 있음 #define MY_NUMBER 123123 // 매크로 상수 // 조건부 컴파일 (멀티 플랫폼 프로그래밍 등) #define MY_PLATFORM #ifdef MY_PLATFORM int num = 1; // 여기서는 이게 컴파일 됨 #else int num = 2; #endif
copy initialization : int a=1.23; // OK
direct initialization : int b(4.56); // OK
uniform initialization (C++11) : int c{7.89}; // error (축소 변환 X)
[일반적인 전역 변수, 함수 사용법]
<ABC.cpp>
#include "ABC.h"
int x = 5; // 정의
int something() { return 1; } // 정의
<ABC.h>
extern int x; // 선언, external linkage 요청
int something(); // 선언, 함수는 기본적으로 external이므로 extern 생략
// 필요한 곳에서 #include "ABC.h"
static_cast : [컴파일 타임에 오류 검사] C-Style과 비슷하지만 타입 오류를 잡아준다. 가장 많이 사용 dynamic_cast : [실행 중에 오류 검사] 다운캐스팅(부모 → 자식)에 사용 (객체지향 내용) reinterpret_cast : 비트열을 변경하지 않고 그저 타입만 변경(재해석) (정수-포인터, 포인터-포인터 변환에 사용) const_cast : const 속성 변환
#include <iostream>
#include <string> // string 클래스 존재
using namespace std;
int main() {
string name = "Jack Jack";
cout << name << endl;
int age = 0;
cout << "Your age : ";
cin >> age; // cin은 버퍼에 whitespace(\n, \t, ' ')를 남김
cin.ignore(32767, '\n'); // 따라서 버퍼에서 \n을 제거해야 getline이 정상적으로 동작
cout << "Your name : ";
getline(cin, name); // getline은 버퍼에서 \n 이전까지 입력받고, \n은 버퍼에서 제거
cout << name << ':' << age << endl;
string a = "Hello ", b = "world";
string c = a + b; // append
cout << c << endl;
for (int i = 0; i < c.size(); i++) {
cout << c[i] << c.at(i) << endl; // index로 접근
}
// compare
if (c == "Hello world") {
cout << "Hi!\n";
}
return 0;
}
enum Color {
// 매크로와 비슷하게 주로 대문자로 쓴다
COLOR_BLACK, // 0
COLOR_RED, // 1
COLOR_BLUE, // 2
COLOR_GREEN = 7, // 7
COLOR_SKYBLUE, // 8
COLOR_ORANGE // 9
};
int main() {
Color myColor = COLOR_RED; // 열거형 변수 사용 (C언어는 enum Color myColor로 선언해야 됨)
// Color myColor2 = 1; (error, 열거형 변수에 정수 직접 대입 불가능)
int myColor3 = COLOR_RED, myColor4 = myColor; // 정수형 변수에 열거형을 대입할 수는 있음
if (myColor4 == COLOR_RED) {
// ok
}
return 0;
}
typedef std::vector<std::pair<std::string,int>> pairlist_t;using pairlist_t = std::vector<std::pair<std::string,int>>;
#include <iostream>
#include <string>
using namespace std;
struct Person {
// 멤버 변수
double height;
float weight = 100.0f; // 초기화를 안해주면 default value로 설정
int age;
string name;
// 멤버 함수
void print() {
// 자신의 멤버에 접근할 수 있다
cout << height << ", " << weight << ", "
<< age << ", (" << name << ')' << endl;
}
};
struct Family {
// 구조체 안에 구조체를 넣는 것도 가능
Person me, mom, dad; // 구조체 변수 사용 (C언어는 struct Person me로 선언해야 됨)
};
Person getMe() {
// 함수 반환값이 구조체일 수도 있다
Person me{178.5, 50.0, 20, "Jack Jack"}; // uniform initialization으로 편하게 초기화
return me;
}
int main() {
Person me_from_func = getMe();
Person me2;
me2.print(); // 멤버 선택 연산자를 사용하여 멤버 함수 호출
// 구조체 간의 대입 (주의 : 기대한 대로 작동이 안 될 수도 있다! 깊은 복사 파트에서 배움)
me2 = me_from_func;
me2.print();
return 0;
}
int x;
cin >> x;
if (cin.fail()) { // cin의 오류 플래그 반환 (잘못된 입력이 들어왔으면 true 반환)
// 오류 플래그가 true이면 cin을 쓸 수 없기 때문에 상태 플래그 초기화를 꼭 해줘야 함
cin.clear(); // cin 상태 플래그 초기화 (주의 : 버퍼 비우기와 관련 없음!)
// 버퍼 비우기 (\n이 나올때까지 최대 32767문자를 제거)
cin.ignore(32767, '\n');
}
int *ptr = new int; // 동적 할당 (실패시 예외(오류) 발생)
delete ptr; // 메모리 해제 (꼭 해줘야 한다! 습관처럼 미리 delete를 써두자)
ptr = nullptr; // dangling pointer 방지
double *ptr2 = new double(3.0); // direct initialization
delete ptr2;
ptr2 = nullptr;
ptr = new int{5}; // uniform initialization
ptr2 = new (std::nothrow) double; // nothrow : 예외를 발생시키지 않음 (실패시 nullptr 반환)
delete ptr;
delete ptr2;
ptr = nullptr;
ptr2 = nullptr;
while (true) {
// memory leak 발생 (이런 실수를 줄이자)
int *test = new int;
}
int length;
cin >> length; // 배열 크기를 사용자에게 입력받음
int *arr = new int[length]; // 동적 할당 배열 생성
delete[] arr; // 메모리 해제
arr = new int[10](); // 길이가 10인 배열 생성, ()를 붙이면 모두 0으로 초기화
delete[] arr;
// uniform initialization
arr = new int[5]{1, 2, 3}; // {num1, num2, ...} -> 순서대로 num1, num2로 초기화, 남는 곳은 0으로 초기화
delete[] arr;
const int *ptr : const int에 대한 포인터. ptr이 저장하는 주소값을 변경하는건 가능, 가리키는 변수의 값을 바꾸는 것은 불가능int *const ptr : int에 대한 const 포인터. 가리키는 변수의 값을 바꾸는 것은 가능, ptr이 저장하는 주소값을 변경하는건 불가능const int *const ptr : const int에 대한 const 포인터. ptr이 저장하는 주소값 변경 및 가리키는 변수의 값 변경 둘 다 불가능
#include <iostream>
using namespace std;
void swap(int &x, int &y) {
int tmp = x;
x = y;
y = tmp;
}
void printRef(const int &x) {
cout << x << endl;
}
int main() {
int x = 5, y = 20;
int &ref = x; // 참조 변수
cout << &x << ' ' << &ref << endl; // x와 ref의 주소값이 같음 (실제로 같은 변수이기 때문에)
ref = 10;
cout << x << ' ' << y << ' ' << ref << endl; // 10 20 10 출력
ref = y;
ref += 1;
cout << x << ' ' << y << ' ' << ref << endl; // 21 20 21 출력
const int &cref = 10; // const 참조 변수는 리터럴로 초기화 가능 (리터럴이 임시변수에 저장됨)
cout << &cref << ' ' << cref << endl; // 주소값도 있고 값도 제대로 출력
// int &ref2 = 10; (error, 일반 참조 변수는 l-value로 초기화해야 됨)
// cref = 30; (error, const 참조 변수는 값 변경 불가능)
int a = 1, b = 2;
swap(a, b); // 참조 변수를 활용한 함수 호출
cout << a << ' ' << b << endl; // 2 1 출력
printRef(12345); // 매개변수가 const 참조 변수이기 때문에 리터럴을 넣어도 된다.
return 0;
}