728x90
반응형

Program Language/C & C++ 112

[C++] 참조(references)

포인터를 사용하면 잠재적으로 많은 양의 데이터를 저렴한 비용으로 전달할 수 있다. 데이터를 복사하는 대신 해당 주소를 포인터 값으로 전달하면 된다. 포인터의 유형은 포인터를 통해 데이터에 수행할 수 있는 작업을 결정한다. 포인터를 사용하는 것은 다음과 같은 몇 가지 면에서 객체 이름을 사용하는 것과 다르다. 다른 구문을 사용한다. 예를 들어 obj 대신 p->m을 사용한다. 포인터가 다른 시간에 다른 객체를 가리키도록 할 수 있다. 객체를 직접 사용할 때보다 포인터를 사용할 때 더 주의해야 한다. nullptr이거나 기대하지 않은 객체를 가리킬 수 있다. 이러한 차이점은 성가실 수 있다. 예를 들어, 일부 프로그래머는 f(&x)가 f(x)에 비해 깔끔하지 못하다고 생각한다. 게다가 다양한 값으로 포인터 ..

[C++] pointer & 소유권

리소스는 획득하고 나중에 해체해야 한다. new에 의해서 획득된 메모리나 fopen()에 의해 열리고 fclose()에 의해 닫힌 파일은 리소스에 대한 가장 직접적인 핸들이 포인터인 리소스의 예다. 이것은 포인터가 프로그램에 쉽게 전달되고 리소스를 소유한 포인터와 리소스를 소유하지 않은 포인터를 구별하는 유형 시스템이 없기 때문에 혼란스러울 수 있다. void confused(int∗ p) { // delete p? } int global {7}; void f() { X∗ pn = new int{7}; int i {7}; int q = &i; confused(pn); confused(q); confused(&global); } 만약에 confused()가 p를 삭제하면 프로그램은 두 번째 두 호출에 대해..

[C++] Pointer & const

C++에서 상수를 나타내기 위해서 두 가지 방법을 제공한다. constexpr : 컴파일 시 평가 const : 수행 중 수정 불가 기본적으로 constexpr의 역할은 compile-time 평가를 가능하게 하고 보장하는 반면, const의 주요 역할은 인터페이스에서 불변성을 지정하는 것이다. 여기서는 인터페이스의 사양에 대해 주로 다룬다. 많은 객체들은 초기화 이후 값이 변경되지 않는다. Symbolic constants는 코드에서 직접 literal을 사용하는 것보다 유지 관리가 더 쉬운 코드로 이어진다. 많은 포인터들이 읽히지만 결코 쓰지 않는 경우가 많다. 대부분의 함수 파라미터들은 읽히지만 쓰지는 않는다. 초기화 후 이러한 불변성 개념을 표현하기 위해 객체 정의에 const를 추가할 수 있다...

[C++] 포인터(Pointer)

T, T*은 T의 포인터의 표현이다. 즉, T*의 변수는 T 객체의 주소를 가질 수 있다. char c = 'a'; char∗ p = &c; // p holds the address of c; & is the address-of operato 포인터에 대한 기본 연산은 역참조, 즉 가리키는 객체를 참조하는 것이다. 이 작업을 간접 참조라고도 한다. 역참조 연산자는 접두사로 '*'을 사용한다. char c = 'a'; char∗ p = &c; // p holds the address of c; & is the address-of operator char c2 = ∗p; // c2 == ’a’; * is the dereference operator p가 가리키는 객체는 c이고, c에 저장된 값은 'a'이므로..

[C++] 별칭

때로는 유형에 대한 새로운 이름이 필요하다. 이유는 다음과 같다. 원래 이름이 너무 길거나 복잡하거나 보기 흉할 때 (프로그래머의 취향) 프로그래밍 기술은 Context에서 동일한 이름을 가진 다른 유형을 요구하기도 한다. 특정 유형은 유지 관리를 단순화하기 위해 한 곳에서만 언급된다. using Pchar = char∗; // pointer to character using PF = int(∗)(double); // pointer to function taking a double and returning an int 유사한 유형은 멤버 별칭과 동일한 이름을 정의할 수 있다. template class vector { using value_type = T; // every container has a v..

[C++] 객체와 값

우리는 이름이 없는 객체를 할당하고 사용할 수 있다. (eg. new를 사용하여 생성) 이상하게 보이는 표현식에 할당하는 것도 가능하다. . 이것은 대상에 대한 가장 단순하고 기본적인 개념이다. 즉, 객체는 연속적인 저장 영역이다. lvalue는 객체를 참조하는 표현식이다. "lvalue"라는 단어는 원래 '할당의 왼쪽에 있을 수 있는 것'을 의미하기 위해 만들어졌다. 그러나 모든 lvalue가 할당의 왼쪽에 사용될 수 있는 것은 아니다. lvalue 유형과 선언은 상수를 참조할 수 있다. const로 선언되지 않은 lvalue는 종종 수정 가능한 lvalue라고 한다. 객체에 대한 단순하고 낮은 수준의 이 개념은 클래스 객체 및 다형성 유형의 객체 개념과 혼동되어서는 안 된다. Lvalues and R..

[C++] decltype 지정자

적절한 생성자가 있다면 auto를 사용할 수 있다. 그러나 때로는 초기화된 변수를 정의하지 않고 유형을 추론하고 싶을 때가 있다. 그런 다음 유형 지정자를 사용할 수 있다. decltype(expr)은 expr의 선언된 유형이다. 이것은 genetic programming에서 주로 유용하다. 내부적으로 다른 요소 유형을 가진 두 개의 행렬을 추가하는 함수를 작성할 때 더하기의 결과의 유형은 무엇이어야 할까? 행렬이지만 요소의 유형은 무엇일까? 명백한 대답은 합계의 요소 유형이 요소의 합계 유형과 같다는 것이다. 따라서 다음과 같이 선언할 수 있다. template auto operator+(const Matrix& a, const Matrix& b) −> Matrix; 반환 유형을 인수 측면에서 표현할 ..

[C++] auto 지정자

생성자가 있는 변수를 선언할 때는 명시적으로 지정하지 않아도 된다. 대신 변수가 초기화 유형을 가지게 할 수 있다. int a1 = 123; char a2 = 123; auto a3 = 123; // a3의 유형은 int가 된다. 정수 literal 타입인 123은 int 다. 그래서 a3은 int가 된다. auto는 초기화되는 유형의 자리 표시자가 된다. 물론 int와 같은 간단한 표현식에서 auto를 사용하는 것은 이점이 없다. 유형이 복잡하고 사용하기 어려울수록 auto는 유용해진다. template void f1(vector& arg) { for (vector::iterator p = arg.begin(); p!=arg.end(); ++p) ∗p = 7; for (auto p = arg.begin..

[C++] 데이터 타입 (bool, char, integer, floating)

bool Boolean : true or false 의 두 가지 값 char Character : 글자 혹은 글을 사용 char : default type signed char : like char. +/- 값을 가질 수 있다. unsigned char : like char. - 값을 가질 수 없다. wchar_t : unicode를 위한 larger character set. char16_t : 16bit character set (UTF-16) char32_t : 32bit character set (UTF-32) Literals int Integer : like char int, signed int, unsigned int, short int, long int, long long int ... in..

[VS] Visual Studio Dependencies(종속성) 설정

VS 프로젝트를 진행할 때, 여러 Lib 프로젝트를 만든 후 가져다 사용하는 경우가 많다. 그럴 경우 컴파일 실행 순서가 뒤죽박죽이면 여러 번 컴파일해야 한다. 왜냐면 가져 다 사용해야 할 Lib이 컴파일이 끝난 상태가 되었을 때 그것을 이용하는 프로젝트가 컴파일이 완료될 수 있기 때문이다. 이런 작업을 위해 컴파일을 순서를 정해주기 위해서는 프로젝트의 종속성을 설정해 줘야 한다. Visual Studio에서는 종속성을 설정하는 기능을 지원한다. 솔루션 이름에서 우클릭(1)하여 속성(2)을 클릭하면 솔루션의 속성을 볼 수 있다. 항목 중에 Project Dependencies를 선택(3)하고 종속성을 설정할 프로젝트를 선택(4) 한다. 해당 프로젝트를 선택하면 이 프로젝트를 제외한 프로젝트들이 나타난다...

[C++] namespace 사용 시 LNK2019 에러 발생

namespace 사용 시, cpp 파일의 활용을 편하기 하기 위해서 namespace를 정확하게 작성하지 않고 using namespace를 사용 시 link 에러가 발생할 수 있다. //header file namespace file_c { void open_file(); } using namespace file_c void open_file() { // ... } 이라고 했을 때, open_file()을 여러 단계를 거치다 보면 2019 LNK ERROR가 발생하는데, 헤드 파일 라이브러리 링크 등 보통의 경우를 모두 체크하더라도 에러가 발생한다. 그렇기 때문에 헤드 파일과 cpp파일 모두에 제대로 된 네임스페이스 형식으로 구현하도록 하자. namespace file_c { void open_fil..

[C++] std::bind 시 변수 메모리 유지 불가

function을 구성할 때 운용하기 쉽도록 하기 위해 bind를 이용하여 매개변수를 미리 넣어둘 수 있다. 하지만 이 방향은 하나의 패키지처럼 묶기기 때문인지 변수의 메모리 주소가 변경되었다. 아래와 같이 간단히 테스트해보면 bind로 묶은 변수 b와 실제 함수에 적용되는 b의 주소 값이 다르다. 결과도 적용되지 않는다. #include #include using namespace std; void add(int a, int& b) { b = a * a; cout

[C++] 변수 묶어 사용하기 (pair, tuple)

함수를 이용할 때 연관된 내용을 동일한 개수만큼 전달하거나 관리해야 할 때 묶어서 사용하곤 한다. 자주 사용되는 경우라면 struct나 class를 이용하여 작업을 할 수도 있지만 임의로 묶어 사용할 때에는 비효율적이다. 이런 점을 해결하기 위해서 C++에서는 pair와 tuple을 지원한다. pair : 2개의 값을 묶고 싶을 때, tuple : 3개의 값을 묶고 싶을 때, pair의 경우에는 웬만한 STL 헤드 파일을 첨부하면 사용할 수 있지만 tuple의 경우에는 을 include 해줘야 한다. pair의 경우에는 make_pair를 tuple은 make_tuple을 사용하면 된다. pair는 first, second를 참조하면 되고, tuple은 get을 이용해야 한다. #include #incl..

[C++] file in/out

C++에서 파일 관련하여 제공하는 Stream 클래스는 다음과 같다. ofstream : 파일에 쓰는 기능의 Stream class ifstream : 파일을 읽는 기능의 Stream class fstream : 파일에 대한 읽고 쓰는 기능을 모두 갖춘 Stream class wifstream : 유니코드 문자로 쓰인 텍스트 파일을 읽는 Stream class wofstream : 유니코드 문자를 텍스트 파일에 쓰는 Stream class #include #include using namespace std; int main() { setlocale(LC_ALL, ""); ofstream fout; fout.open("D:\\sample.txt"); fout

[C++] RAII Pattern

C++ 에는 RAII (Resource Acquisition Is Initialization)이라는 패턴이 있다. 리소스의 획득은 초기화다라는 뜻인데 보통 RAII Design Pattern이라고 한다. 예를 들자면, lock_gaurd class가 있다. class lock_guard {// class with destructor that unlocks mutexes public: explicit lock_guard(_Mutexes&... _Mtxes) : _MyMutexes(_Mtxes...) {// construct and lock _STD lock(_Mtxes...); } lock_guard(_Mutexes&... _Mtxes, adopt_lock_t) : _MyMutexes(_Mtxes...) ..

[C++] std::thread 종료 (abort() has been called)

std::thread를 사용하다 보면 abort() has been called라는 에러 메시지를 만나는 경우가 있다. 이는 thread가 종료되기 전에 시스템이 종료되거나, 객체가 사라질 때 발생한다. 이 때는 join()을 사용해서 해결하면 된다. #include #include using namespace std; int total; void sum() { for (int i = 0; i < 200000; i++) total += 1; } int main() { while (1) { total = 0; std::thread th1(sum); std::thread th2(sum); cout

[C++] 스마트 포인터

스마트 포인터는 에 정의되어 있고, RAII 또는 리소스 획득 초기화 프로그래밍 관용구에 매우 중요하다. 스마터 포인터의 목표는 개체의 모든 자원 생성이 한 줄의 코드에서 만들어지고 준비되어 그 개체가 초기화되는 동시에 자원 수집이 발생하는 것을 확인하는 것이다. 이전 포인터 선원과 비교하면 아래와 같다. void UseRawPointer() { Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); // Use pSong delete pSong; } void UseSmartPointer() { unique_ptr song2(new Song(L"Nothing on You", L"Bruno Mars")); // Use song2 // delete automa..

728x90
반응형