- 2012년 그들이 스터디를 시작한다.
- C/C++/Java 모두 다른 언어지만 하나에서 시작했으니...
- ALGOL계 언어라고도 한다고 한다.. 궁금해 할 사람을 위해
- 그러나 비슷한 시기에 탄생한 Fortran, lisp등을 제하고 이후 대부분의 언어에게 영향을 주었으니 ALGOL과 무관한 언어가 있을까..
- ALGOL계 언어라고도 한다고 한다.. 궁금해 할 사람을 위해
3.1.2. c++의 "hello world" 프로그램을 뜯어보자 ¶
#include <iostream> using namespace std; int main(){ cout<<"hello!"<<endl; return 0; }
- #이 붙어있는 명령어 - Preprocessor가 처리
- #include, #define, #ifndef 등...
- 나중에 배우겠지만 이건 안쓸수록 좋음 - 안혁준
- 왜? 컴파일러는 이런거 모르기 때문.
- 왜? 컴파일러는 이런거 모르기 때문.
- #include, #define, #ifndef 등...
- namespace : 이름 중복을 막기 위해 사용
- using namespace NAME; -> NAME의 namespace를 해당 scope 안에서 이용하겠다는 것
- using namespace NAME; -> NAME의 namespace를 해당 scope 안에서 이용하겠다는 것
- std
- 기본 함수들의 namespace
- 기본 함수들의 namespace
- using
- 지금부터 어떤 특정 네임스페이스를 쓰겠다는 지시어.
- 지금부터 어떤 특정 네임스페이스를 쓰겠다는 지시어.
- 문자열
- char의 배열, null terminated char sequence
- 자바에서는 아닌것 처럼 보여도 사실 내부적으로는 비슷하다.
- string Class
- char의 배열, null terminated char sequence
- endl
- 라인끝 문자를 출력하고 버퍼를 비운다.
- 라인끝 문자를 출력하고 버퍼를 비운다.
- return 0;
- UNIX/LINUX 계열에서는 중요한 정보
- 이걸로 프로그램이 제대로 끝났는지 판단한다.
- return에는 중요한 특성이 있는데 이게 호출되면 지역변수를 정리한다.
- main 함수의 리턴값
- UNIX/LINUX 계열에서는 중요한 정보
3.1.3. 변수 ¶
- 정의 - 어떤 값을 담을수 있는것.
- C/C++/JAVA은 형을 강제하는 강형언어기 때문에 형이 있다.
- 당연히 강형언어가 더 빠르게 동작할수 있다. CPU에서 어떤 모듈을 쓰는지 알기 때문.
- 당연히 강형언어가 더 빠르게 동작할수 있다. CPU에서 어떤 모듈을 쓰는지 알기 때문.
- C/C++/JAVA은 형을 강제하는 강형언어기 때문에 형이 있다.
- 정수
- int, long, long long, short, char
- int크기는 CPU가 한번에 처리할수 있는 정수 - 당연히 16bit에서는 다를수 있다.
- long long 같은 경우에는 없을수도 있다.
- int, long, long long, short, char
- 실수
- float, double
- float가 float인 이유 - 부동 소수점이라서....
- double 은 그냥 double float라서..
- float가 float인 이유 - 부동 소수점이라서....
- float, double
- bool
- 1bit 짜리.
- C는 bool이 없다!, c++은 있다. java는 boolean으로 사용한다. - C11은 있단다.
- 대부분의 경우 그냥 정수로 처리한다.
- 값이 0이면 false 그외는 true
- c++에서도 0은 false로, 그외는 true로 간주된다. while(1) {}, while(true) {} 둘 다 가능
- java에서는 int와 boolean은 호환되지 않는다. while(1) {}는 컴파일에러.
- 값이 0이면 false 그외는 true
- 1bit 짜리.
3.1.4. 제어문, 반복문 ¶
- 제어문과 반복문은 어찌보면 동치.
- switch case문에서 case는 컴파일러만 알뿐(Label이라는 소리..)
- 세 언어에서 case문 뒤는 "정수" 이다.
- ASCII에 속지마라.
- java7부터 문자열상수 case label 지원. case "hello": ...; 가 된다.
- ASCII에 속지마라.
3.2.2. 함수 (Function) ¶
- function이란 input과 output이 있는 기능 단위
- 함수에 parameter 를 넘겨주지 않거나 return 이 없는 함수도 있음.
- 함수에 parameter 를 넘겨주지 않거나 return 이 없는 함수도 있음.
- 많은 기능을 잘게 쪼개기 위해 함수를 사용한다.
- 가독성을 좋게 한다.
- 코드의 재사용성을 높인다.
- global variable의 사용을 자제하자. 함수의 기능을 이해하기 어렵게 만든다.
- 변수 접근을 제어하기 힘들기 때문에 버그를 유발할 확률도 증가한다.
- 변수 접근을 제어하기 힘들기 때문에 버그를 유발할 확률도 증가한다.
- 파라메터 전달 방식
- call by value
- call by pointer
- call by reference(alias)
- call by value
- C/C++/Java의 parameter는 call-by-value 형식으로 값을 전달한다.
- 포인터 값을 전달하는 Call-by-reference의 경우는, 포인터 값을 복사의 방식으로 전달하게 되므로, 일종의 call-by-value라고 볼 수 있다.
- 참조는 내부적으로 포인터를 이용한다.
- C/C++의 함수 호출 방법(Calling Convention)
- __stdcall, __thiscall, __pascal, __syscall 등
- 인자의 전달 방식과 stack의 해제 방법의 차이
- 인자의 전달 방식과 stack의 해제 방법의 차이
- 함수 decorator : C++의 오버로딩을 하게 되면, 컴파일 타임에서 각각의 함수를 구분할 수 있도록 붙는 머릿말
- extern "C"를 이용하면 이러한 함수 decorator가 없어진다.
- extern "c"의 의미?
- c++11(아마도?) Working Draft의 7.5절 linkage specification 참고
- extern "c"의 의미?
- __stdcall, __thiscall, __pascal, __syscall 등
3.4. 2013년 1월 22일 ¶
- 실습. 선형대수학 계산기를 만들어보기
- #ifndef NAME : #define NAME이 되어있지 않는 경우에 작동한다. 주로 헤더파일 중복 include를 막기 위해 사용한다.
~cpp #ifndef _HEADER_FILE_NAME_ // naming rule이 따로 있는진 모르겠음 #define _HEADER_FILE_NAME_ ... // header source ... #endif _HEADER_FILE_NAME_
- #pragma once도 동일한 효과를 준다. 전체 소스코드를 단 한번만 include 한다. (비표준)
- 비표준이지만 거의 모든 컴파일러가 지원하므로 defacto
- 비표준이지만 거의 모든 컴파일러가 지원하므로 defacto
~cpp #pragma once
- const 멤버 함수의 효과
- return되는 값을 참조하는 구문을 작성하면 dangling pointer 위험이 있다.
- move constructor(?)
- 연산자 오버로딩 : C++에서는 operator를 이용해서 연산자에 특정 기능을 정의할 수 있다. C와 자바에서는 안 된다.
- 연산자 오버로딩에서 friend가 필요했던 이유!
- int와 객체와의 곱셈을 구현, 남의 멤버함수
- int와 객체와의 곱셈을 구현, 남의 멤버함수
- 오토박싱, 언박싱(자동으로 형태를 변환해준다?)
- <<는 shift 연산자에 오버로딩 한 것 (stream)
- 연산자 오버로딩을 한 경우, 객체 u와 v가 있으면, u+v == u.operator+(v) 와 같다.
3.5. 2013년 1월 29일 ¶
- 신기한 포인터 놀이
- 참고 : Cpp에서의멤버함수구현메커니즘
- 참고 : Cpp에서의멤버함수구현메커니즘
class foo { void hello(void) { cout << "hello" << endl; } }이렇게 정의 해 놓은 상태에서
int main() { foo *bar = NULL; bar->hello(); }이렇게 작성해서 실행하면, 보기에는 실행이 안 될 것 같지만 실행이 된다.
- 인스턴스는 NULL를 가리키지만, 실제로 실행될 때는 hello 함수만을 호출하기 때문이다. (문장 설명이 부족한데?)
- stack이나 heap에서 데이터를 free 할 때, 실제로 포인터만 이동이 된다. 그래서 실제로는 데이터가 메모리에 남아있게 된다(기존의 값을 초기화화 할 필요없이 할당 플래그만 해제하면 되므로). 중간에 다른 곳에서 호출이 될 경우에 데이터가 덮어 써지는 문제가 발생할 수 있으므로, dangling pointer를 조심해야 한다.
- 이 이야기는 os의 가용 메모리 풀과 상관이 있군 - 서지혜
- 이 이야기는 os의 가용 메모리 풀과 상관이 있군 - 서지혜
- ostringstream -> stream에 뭔가 하면 string으로 나온다
- 가변 인수 void NAME (int name, …)
'…'은 가변 인수를 표현한 것이다.
void Func(int 고정인자, …) { va_list ap; va_start(ap, 고정인자); va_arg(ap, 인수타입); -> 가변 인수를 읽는 명령 va_end(ap); }
- 형은 보장하지 않는다. 가변인자들의 형을 강제할 수 없기 때문에 stack에 void*로 저장된다. 그리고 최소한 인자가 하나는 있어야 한다.
예시 코드
#include <iostream> #include <cstdarg> using namespace std; void test(int num, ...) { va_list ap; va_start(ap, num); for(int i=0; i<num; i++) { cout << va_arg(ap, int) << endl; } va_end(ap); } int main(void) { test(5, 1,2,3,4,5); return 0; }
- stl vector를 이용한 class vector 만들기
- namespace로 같은 이름을 가진 클래스들을 사용해보자
- namespace로 같은 이름을 가진 클래스들을 사용해보자
- template과 friend
- template와 friend 사이에 여러 매핑이 존재한다. many to many, one to many, many to one, one to one : 참고
- template와 friend 사이에 여러 매핑이 존재한다. many to many, one to many, many to one, one to one : 참고
- c++11에서 auto의 의미가 달라졌다??
3.6. 2013년 2월 13일 ¶
- 가변인자의 취약점을 이용한 공격 (Format String Attack)
- 참고 : http://www.hackerschool.org/HS_Boards/data/Lib_system/The_Mystery_of_Format_String_Exploitation.pdf
- 가변인자의 형을 검사하는 주체가 컴파일러가 아닌, 함수이기 때문이다.
- 참고 : http://www.hackerschool.org/HS_Boards/data/Lib_system/The_Mystery_of_Format_String_Exploitation.pdf
- private의 상속
- private 상속을 받게 되면, 클래스 내에서만 사용할 수 있고, 외부에서는 접근을 할 수 없다. 부모 클래스가 가상함수를 가지고 있고, 이것을 재정의 해서 사용할 수 있다.
- 어떤 클래스를 쓰되, 외부에 공개하지 않고, 가상함수를 상속받아야 할 때 사용할 수 있다.
- (사실 people 클래스 안에 DataInfo를 멤버 변수로 선언해서 사용해도 되긴 하다. 하지만 private 상속을 받을 때 보다 메모리를 더 많이 사용하게 되기 때문에, private 상속을 쓰는 게 좋다.)
- (사실 people 클래스 안에 DataInfo를 멤버 변수로 선언해서 사용해도 되긴 하다. 하지만 private 상속을 받을 때 보다 메모리를 더 많이 사용하게 되기 때문에, private 상속을 쓰는 게 좋다.)
- private 상속을 받게 되면, 클래스 내에서만 사용할 수 있고, 외부에서는 접근을 할 수 없다. 부모 클래스가 가상함수를 가지고 있고, 이것을 재정의 해서 사용할 수 있다.
- #define와 typedef의 차이
- #define은 매크로이기 때문에, preprocessor에 의해서 처리되고, typedef는 compiler에 의해 처리된다.
- #define은 매크로이기 때문에, preprocessor에 의해서 처리되고, typedef는 compiler에 의해 처리된다.
- 함정 카드 문제 (thanks to 서지혜 누나)
int a, b =5; a= b++ + ++b + ++b + ++b + b++ ;
- a의 값은 뭘까?
- ++b(1st), +(2nd), b++(3rd), =(4th)
- 연산은 오른쪽에서 왼쪽으로 진행.
- ++b(1st), +(2nd), b++(3rd), =(4th)
- container의 종류
- standard STL sequence container
- vector(메모리가 연속적인 (동적) 배열), string, deque(double ended queue, 덱이라고도 한다. 참고), list(linked-list)
- vector(메모리가 연속적인 (동적) 배열), string, deque(double ended queue, 덱이라고도 한다. 참고), list(linked-list)
- standard STL associate container
- set(집합, 순서가 없는 리스트, 중복을 허용 안함), multiset, map(key와 value가 짝을 지어서 set으로 저장된다), multimap (set과 map은 input 될 때, valanced tree 형태로 저장되기 때문에 search time이 항상 log n을 유지할 수 있다. 즉, 들어온 순서와 정렬 순서가 일치하지 않게 된다.)
- set(집합, 순서가 없는 리스트, 중복을 허용 안함), multiset, map(key와 value가 짝을 지어서 set으로 저장된다), multimap (set과 map은 input 될 때, valanced tree 형태로 저장되기 때문에 search time이 항상 log n을 유지할 수 있다. 즉, 들어온 순서와 정렬 순서가 일치하지 않게 된다.)
- standard STL sequence container
- non-standard sequence container
- slist(single-list), rope(대용량 string)
- slist(single-list), rope(대용량 string)
- non-standard associate container
- hash-set(hash 계열들)
- 도서관 == hash system (책 마다 고유 번호가 붙어있음)
- hash는 메모리를 많이 먹는다.
- 도서관 == hash system (책 마다 고유 번호가 붙어있음)
- hash-set(hash 계열들)
- not in STL container
- bitset, valarray, stack, queue
- bitset, valarray, stack, queue
- 위의 각각의 예시는 메모리 기반, node 기반(linked-list)으로 구분이 된다.
- vector<bool>은 일반적인 vector 연산이 불가능한데, 이걸 해결하기 위해 bitset을 이용한다.
- set과 hash-set
- set은 valanced tree 형태로 저장된다. hash-set은 순서가 보장이 되지 않는다.
- string과 vector<char> -> 참조 카운팅을 안 하기 때문에, vector로 쓸 경우 더 빠를 수 있다.
- 삽입과 삭제시 transaction(작업 하다가 오류가 날 경우, 돌아갈 수 있는 기능)이 가능한 경우
- list는 보장됨. vector는 보장되지 않음
- 무효화가 적어야 하는 경우에는 node 기반(list, set)을 사용해야 한다.
- 무효화가 적어야 하는 경우에는 node 기반(list, set)을 사용해야 한다.
- set은 valanced tree 형태로 저장된다. hash-set은 순서가 보장이 되지 않는다.
- vector<bool>은 일반적인 vector 연산이 불가능한데, 이걸 해결하기 위해 bitset을 이용한다.
ArrayList arr; //arr.size() = 10; for(int i=0; i<10; i++) { arr.delete(i); } arr.size == 0; (???)
- 이렇게 작성했을 때, arr.size는 0이 되지 않는다는 것을 확인할 수 있다.
- arr.size()는 녕원히 0이 되지 않는다.. naver.. i가 5일 때 ArrayIndexOutOfBounds Exception이 발생한다
- arr.size()는 녕원히 0이 되지 않는다.. naver.. i가 5일 때 ArrayIndexOutOfBounds Exception이 발생한다
- vector의 삽입, 삭제가 일어날 때, 전체 배열 크기가 제한 크기(1024)를 넘어갈 경우, 2배 크기의 배열을 만들게 되는데, 이 때 각각에 해당하는 포인터가 전부 바뀌게 되므로 '무효화' 되는 것이다.
- 그런데, 정확한 무효화 시점을 알 수 없으므로, 언제든지 무효화 될 수 있다고 생각하는 것이 좋다.
- qsort 작성을 위해서는 함수 포인터를 지정해야 하는데, C++의 클래스를 이용하면 이것을 생략할 수 있다.
vector <widget *> ar; ar,push_back(new widget()); ar.pop();
- 이렇게 될 경우, widget은 계속 생성되는데, pop을 하면, 만들어진 widget은 계속 메모리에 상주하고, widget을 가리키고 있는 ar 항목들만 삭제된다. 그래서, shared_ptr을 사용한다.
- tr1은 C++0x에서 제정된 것들이 tr1 namespace로 정의되어 있었는데 C++11이 나오면서 다 통합되었다고 한다.
- boost는 c++ library인데, 주요 쓰는 함수나 패턴들을 다 모아 놓은 것들이다. (java의 jUnit 같은 거?)
vector v;
일 때
if(v.size()==0)
이것 보다는
if(v.empty());를 써서 공백인지 확인한다.
- 속도가 빠르다. size를 구하는 과정이 생략되고, 오류를 줄일 수 있다.
- vector의 swap
- vector의 reserve
- for문을 이용해서 100개를 할당하는 것 보다, reserve(100)을 해서 할당하는 것이 효율적이다.
- for문을 이용해서 100개를 할당하는 것 보다, reserve(100)을 해서 할당하는 것이 효율적이다.
- vector의 resize
- resize는 reserve의 할당하는 역할에 초기화까지 해 준다.
- resize는 reserve의 할당하는 역할에 초기화까지 해 준다.
3.8. 다음주 예고? ¶
- ??
- 이 네이밍은 필시 튜터의 최근 드라마 성향이 반영된 것일게야... - 김태진
- 오오 점점 재미있어진다
- 화요일에 하겠다고 한 사람들이 보이지 않는군요...=ㅅ= -김태진
- 매우 애석하게도 내가 가지를 못 하니....... 하필 수요일....... - 황현
- 이번주까지 수요일 저녘이니까 시간 바꿀수 있을듯ㅋㅋ 되는날 말해 - 서지혜
- 이번주까지 수요일 저녘이니까 시간 바꿀수 있을듯ㅋㅋ 되는날 말해 - 서지혜
- 다음시간부턴 이론보단 실습 위주로 가는게 좋을 것 같아요. 백문이불여일타기도 하고 참여자간의 갭을 빠르게 줄이는 방법이고.. - 서지혜
- 22일부터 화요일 오후 3시입니다 - 조광희
- 구글 행아웃 정말 좋네요ㅋㅋㅋㅋ 그렇다고 튜터가 집에서 원격으로 강의해서는 아니되옵니다ㅋㅋㅋㅋ - 김민재
- 행아웃으로 하는 강의 재미있었습니다. 껄껄껄 - 권영기