반응형

객체지향 프로그래밍의 개념

  • 프로그램에서 필요한 데이터 타입을 먼저 설계

  • C언어의 구조체를 사용하면 새로운 데이터 타입을 정의 가능

  • C 구조체 : 데이터만 포함 할 수 있음

  • C++ 구조체 : 데이터, 함수 포함 가능

C Style(구조체 없이 구현)

void Add(int xr, int xi, int yr, int yi, //in parameters
    int* sr, int* si) // out parameters
{
    *sr = xr + yr;
    *si = xi + yi;
}

int main()
{
    int ar = 1, ai = 1;
    int br = 2, bi = 2;
    int sr, si;

    Add(ar, ai, br, bi, &sr, &si);
}

C Style(구조체를 사용한 구현)

Complex Add(const Complex& c1, const Complex& c2)
{
    Complex temp;
    temp.re = c1.re + c2.re;
    temp.im = c1.im + c2.im;
    return temp;
}

int main()
{
    Complex c1 = { 1, 1 };
    Complex c2 = { 2, 2 };

    Complex t = Add(c1, c2);
}

 

Stack으로 배우는 OOP

Step1. 구조체 없이 전역으로 구현한 Stack

  • 쉽게 구현하였으나 Stack을 다중으로 사용하기에는 적절하지 않음

int buf[10];
int idx = 0;

void push(int n) { buf[idx++] = n; }
int pop() { return buf[--idx]; }

int main()
{
    push(10);
    push(20);
    push(30);

    std::cout << pop() << std::endl;
}

Step2. 구조체를 사용한 Stack

  • Stack 구조체를 사용하지 않았을때 보단 간결하지만 Stack 상태 조작 함수가 외부에 있음

struct Stack
{
    int buf[10];
    int idx;
};

void push(Stack* s, int n) 
{ 
    s->buf[(s->idx)++] = n; 
}
int pop(Stack* s) 
{ 
    return s->buf[--(s->idx)]; 
}

int main()
{
    Stack s1, s2;
    s1.idx = 0;
    s2.idx = 0;

    push(&s1, 10);
    push(&s1, 20);
    push(&s1, 30);

    std::cout << pop(&s1) << std::endl;
}

Step3. C++ 구조체를 사용한 Stack

  • 구조체에 데이터와 함수를 함께 구현

  • idx가 잘못된 값으로 초기화 위험성 있음
struct Stack
{
    int buf[10]; // 멤버 데이터
    int idx;

    void push(int n) // 멤버 함수
    {
        buf[idx++] = n;
    }
    int pop() // 멤버 함수
    {
        return buf[--idx];
    }
};

int main()
{
    Stack s1, s2;
    s1.idx = 0;
    s2.idx = 0;

    s1.push(10);
    s1.push(20); 
    s1.push(30); // 컴파일러에 의해서 내부적으로는 push(&s1, 20) 형태로 사용됨

    std::cout << s1.pop() << std::endl;
}

Step4. 정보 은닉(Information Hiding)

 

  • 접근 지정자
    • private : 멤버 함수에서만 접근 할 수 있음
    • public : 외부 함수에서 접근 가능
  • 정보 은닉(information hiding)
    • 멤버 데이터를 외부에서 직접 접근할 수 없게 하고, 멤버 함수를 통해서만 접근 가능하도록 함
    • 외부에 잘못된 사용으로 부터 객체가 불안해 지는것을 방지
    • Stack을 사용하는 사람은 push, pop 함수만 알면 되지 Stack  내부 데이터를 몰라도 됨
  • struct vs class
    • struct : 접근 지정자 생략시 기본 접근자 public
    • class : 접근 지정자 생략시 기본 접근자 private
class Stack
{
// class 접근 기본값은 private
    int buf[10];
    int idx;

public: // 외부 접근을 위한 public 접근자
    void init() { idx = 0; }
    void push(int n)
    {
        buf[idx++] = n;
    }
    int pop()
    {
        return buf[--idx];
    }
};

int main()
{
    Stack s1;
    s1.init();

    s1.push(10);
    s1.push(20);
    s1.push(30);

    std::cout << s1.pop() << std::endl;
}

Step5. 생성자(Constructor)

  • 클래스이름과 동일한 이름을 가지는 함수

  • 객체를 만들면 자동으로 생성자가 호출됨
  • 리턴 타입을 표지하지 않음
  • 인자 사용 여부는 선택적
class Stack
{
    int buf[10];
    int idx;

public:
    // 클래스 이름과 동일한 함수 : 생성자
    Stack() { idx = 0; }
    void push(int n) { buf[idx++] = n; }
    int pop() { return buf[--idx]; }
};

int main()
{
    Stack s1;

    s1.push(10);
    s1.push(20);
    s1.push(30);

    std::cout << s1.pop() << std::endl;
}

Step6. 소멸자(Destructor)

  • 스택의 버퍼크기를 변경 할 수 있도록 제공을 위해선 동적 메모리 할당이 필요한데 객체가 소멸되는 시점에 메모리 해지를 위해서 소멸자 이용
  • ~클래스이름() 형태의 함수

  • 객체가 파괴될 때 호출됨
class Stack
{
    int* buf;
    int idx;

public:
    // 생성자 : 객체가 생성될때 자동으로 호출
    Stack(int size = 10) 
    { 
        buf = new int[size]; // new 배열 타입으로 동적 메모리 할당
        idx = 0;
    }
    // 소멸자 : 객체가 파괴될때 자동으로 호출
    ~Stack() 
    {
        delete[] buf; // new 배열 타입으로 할당한 메모리를 delete[]로 해지
    }
    void push(int n) { buf[idx++] = n; }
    int pop() { return buf[--idx]; }
};

int main()
{
    Stack s1(20);
    s1.push(30);
    std::cout << s1.pop() << std::endl;
}

Step7. 선언과 구현의 분리

  • 선언과 구현의 분리

    • 클래스 선언 안에는 함수의 선언만 포함

    • 함수의 구현은 클래스 외부에서 구현

  • 선언 파일과 구현 파일의 분리

    • 클래스 선언부는 헤더 파일로 생성(.h)

    • 클래스 구현부는 소스 파일로 생성(.cpp)

// stack.h
class Stack
{
private:
    int* buf;
    int idx;

public:
    Stack(int size = 10);
    ~Stack();
    void push(int n);
    int pop();
};
// stack.cpp
#include "Stack.h"

Stack::Stack(int size = 10)
{
    buf = new int[size];
    idx = 0;
}
Stack::~Stack()
{
    delete[] buf;
}
void Stack::push(int n) 
{ 
    buf[idx++] = n; 
}
int Stack::pop() 
{ 
    return buf[--idx]; 
}
// main.cpp
#include <iostream>
#include "Stack.h"

int main()
{
    Stack s1(20);
    s1.push(30);
    std::cout << s1.pop() << std::endl;
}

Step8. 코딩 관례

  • 대부분의 오픈소스들은 프로젝트들은 사용자 친화적으로 public 함수를 상단, private 함수, 변수는 하단에 배치하는 경향을 보임

// Stack.h
class Stack
{
public: // 주 접근 함수를 상단
    Stack(int size = 10);
    ~Stack();
    void push(int n);
    int pop();
    
private: // 내부 접근 함수 및 변수는 하단
    int* buf;
    int idx;    
};

 

Step9. class template

  • Stack은 int 뿐 아니라 다른 타입버전도 필요하므로 템플릿을 이용하여 구현

  • 내부적으로는 컴파일 타임에 사용자 코드를 기반으로 각각의 데이터 타입별 Stack 클래스를 별도로 생성함
  • 클래스 템플릿에서 멤버 함수 구현시 주의사항
    • 클래스 외부, 내부에 구현부를 분리하여 넣어도 되지만, 별도의 소스파일로 분리하면 안됨
    • 함수 선언과 구현 모두 헤더파일에 존재 하여야함
template<typename T>
class Stack
{
    T* buf;
    int idx;

public:
    Stack(int size = 10) { 
        buf = new T[size];
    }
    ~Stack() {
        delete[] buf;
    }
    void push(T n) { buf[idx++] = n; }
    T pop() { return buf[--idx]; }
};

// 구현부 분리 시
template<typename T>
Stack<T>::Stack(){}

template<typename T> 
T Stack<T>::pop(){}


int main()
{
    Stack<int> s1(20);
    s1.push(30);

    Stack<double> s2(20);

    std::cout << s1.pop() << std::endl;
}

Step10. STL stack

  • STL

    • C++ 표준 라이브러리
    • 다양한 자료구조와 알고리즘 함수 제공
  • stack
    • 내부 버퍼 크기는 자동으로 관리됨
    • 템플릿으로 구현 됨
    • 제거용 함수와 리턴용 함수가 분리 되어 있음
      • pop : 제거만 하고 리턴 안됨
      • top : 리턴만 하고 제거되지 않음
int main()
{
    std::stack<int> s;
    s.push(10);
    s.push(20);
    s.push(30);

    int n1 = s.top(); // return 30(리턴만 하고 제거 X)
    int n2 = s.top(); // return 30(리턴만 하고 제거 X)
    s.pop(); // 제거만 하고 리턴 X
    int n3 = s.top(); // return 20
    s.pop(); // 제거만 하고 리턴 X
    int n4 = s.top(); // return 10
}

 

반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ 복사 생성자  (0) 2019.05.06
C++ 접근 지정자, 생성자, 소멸자  (0) 2019.05.06
C++ Explicit Casting  (0) 2019.05.06
C++ reference 변수  (0) 2019.05.06
C++ new  (0) 2019.05.06

반응형

C 캐스팅의 문제점

  • 다른 데이터 타입의 포인터형으로 캐스팅이 가능
  • 캐스팅시 상수 주소를 비상수 포인터에 담을 수 있음
  • 이외 버그 가능성이 있는 캐스팅도 허용함
int main()
{
    int n = 3;
    double* p1 = (double*)&n; // 다른 데이터 타입 포인터로 캐스팅

    const int c = 10;
    int* p2 = (int*)& c; // 상수 주소를 비상수 포인터로 캐스팅
}

C++ 4가지 캐스팅

  • static_cast : 컴파일 타임 캐스팅
    • 가장 기본적인 캐스팅, 위험성을 내포한 경우는 캐스팅 안됨.
    • void* -> 다른타입*
  • reinterpret_cast : 컴파일 타임 캐스팅
    • 메모리의 재해석
    • 서로 다른 타입의 주소 캐스팅
    • 포인터와 정수간 캐스팅
  • const_cast : 컴파일 타임 캐스팅
    • 객체의 상수성을 제거하는 캐스팅
  • dynamic_cast : 실행시간 캐스팅
    • down cast 막기 위함
    • RTTI 기능
int main()
{
    int* p1 = static_cast<int*>(malloc(100)); // ok

    // 서로 다른 타입의 포인터로 캐스팅 필요시
    int n = 3;
    double* p2 = static_cast<double*>(&n); // error
    double* p2 = reinterpret_cast<double*>(&n); // ok

    // 상수를 비상수로 캐스팅 필요시
    const int c = 10;
    int* p3 = static_cast<int*>(&c); // error
    int* p3 = const_cast<int*>(&c); // ok
    
    // 응용
    double* p = (double*)&c; // 과거 C 스타일
    double* p = reinterpret_cast<double*>(const_cast<int*>(&c)); // 상수성 제거, 타입 호환
}
반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ 접근 지정자, 생성자, 소멸자  (0) 2019.05.06
C++ OOP(Object Oriented Programming)  (0) 2019.05.06
C++ reference 변수  (0) 2019.05.06
C++ new  (0) 2019.05.06
C++ 함수 특징 #2  (0) 2019.05.05

반응형

reference 변수

  • 기존 메모리(변수)에 새로운 이름(alias)을 부여하는 것
  • 레퍼런스 변수는 메모리를 할당하지 않는가?
    • 단순한 코드의 경우 메모리를 사용하지 않음
    • 복잡한 경우(함수 인자로 사용되거나...) 상황에 따라 내부적으로 포인터를 사용
    • C++ 표준 문서는 레퍼런스의 동작만 정의 할뿐, 구현은 정의하고 있지 않음
  • 반드시 초기화 되어야 함
int main()
{
    int n = 10; // 일반 변수
    int* p = &n; // 포인터 변수

    int& r = n; // 레퍼런스 변수
}

 

Call By Reference

  • 함수 인자의 값을 변경하게 하려면 포인터 또는 레퍼런스를 사용
void Inc1(int n) { ++n; }
void Inc2(int* p) { ++(*p); }
void Inc3(int& r) { ++r; }

int main()
{
    int a = 10, b = 10, c = 10;

    Inc1(a); // call by value
    Inc2(&b); // call by pointer
    Inc3(c); // call by reference

    std::cout << a << std::endl; // 10
    std::cout << a << std::endl; // 11
    std::cout << a << std::endl; // 11
}
int main()
{
    int n = 0;
    scanf("%d", &n); // 인자를 포인터로 전달(call by pointer)
    std::cin >> n; // 인자를 레퍼런스로 전달(call by reference)
}

 

Call by const Reference

  • 함수의 인자로 사용한 변수의 값을 변경되지 않게 하려면
    • Call by value : 동일한 객체가 메모리에 중복 생성됨
    • Const Reference : 메모리 중복 생성이 되지 않고 생성자, 소멸자의 호출을 차단 할 수 있음
  • 권장 사항
    • primitive type : Call by value // C++에서 기본 제공 타입
    • user defined type : Const reference // 사용자 정의 타입
struct Data // user defined type
{
    char data[1000];
};

void Foo1(int a) {} // primitive type(call by value)

void Foo2(const Data& a) {} // user defined type(call by const reference)

int main()
{
    Data x;

    Foo1(1);
    Foo2(x);
}

 

Reference return

  •  함수 인자
    • call by value : 복사본 생성
    • call by reference : 복사본 미생성
  • 함수 리턴
    • return by value : 복사본(임시 객체)을 리턴(등호 왼쪽에 올 수 없음, lvalue가 될 수 없음)
    • return by reference : 원본 리턴(지역 변수는 참조로 리턴하면 안됨)
struct Point
{
    int x, y;
};

void F1(Point p) {} // 복사본 생성
void F2(Point& r) {} // 복사본 생성X

Point pt;
Point& Goo() { return pt; }

int main()
{
    Goo().x = 20;

    std::cout << pt.x << std::endl; // 20
}

 

rvalue reference

  • lvalue vs rvalue
    • rvalue : 등호(=)의 오른쪽에만 올 수 있는 것
    • lvalue : 등호(=)의 오른쪽과 왼쪽에 모두 올 수 있는 것
  • reference 규칙
    • lvalue reference : lvalue만 가리킬 수 있음
    • const lvalue reference : lvalue, rvalue  모두 가리킬 수 있음
    • rvalue reference : rvalue만 가리킬 수 있음
  • rvalue reference 활용 분야
    • move semantics
    • perfect forwarding
int main()
{
    int v1 = 0, v2 = 0;

    v1 = 10; // ok
    10 = v1; // error
    v2 = v1;

    // lvalue reference
    int& r1 = v1; // ok
    int& r2 = 10; // error

    // const lvalue reference
    const int& r3 = v1; // ok
    const int& r4 = 10; // ok

    // rvalue reference
    int&& r5 = v1; // error
    int&& r6 = 10; // ok

}
반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ OOP(Object Oriented Programming)  (0) 2019.05.06
C++ Explicit Casting  (0) 2019.05.06
C++ new  (0) 2019.05.06
C++ 함수 특징 #2  (0) 2019.05.05
C++ 함수 특징 #1  (0) 2019.05.05

반응형

동적 메모리 할당

  • 동적 메모리 할당이 필요한 이유
    • 실행 시간에 결정된 크기 만큼의 메모리를 할당하고 싶을때
    • 자동으로 메모리를 해지 하지 말고, 사용자가 원할때 명시적인 해제를 위해
  • C 언어
    • malloc으로 할당하고 free로 해지
    • malloc 사용시 주소를 원하는 타입으로 캐스팅 필요
  • C++ 언어
    • new로 할당하고 delete로 해지
    • 원하는 타입의 주소를 리턴하므로 캐스팅 불필요
    • new 배열로 할당한 경우 delete[]로 해지(배열을 delete로 해지 시 동작에 대해서는 알수없음 undefined)
    • malloc은 생성하지 호출하지 않지만 new는 생성자를 호출함
int main()
{
    int cnt = 0;

    std::cout << "학생수 ? >>";
    std::cin >> cnt;

    // 학생수 만큼의 메모리 할당이 필요하다.
    int score[cnt]; // g++ ok, vc++ error

    // C Style
    int* p1 = (int*)malloc(sizeof(int) * 10);
    free(p1);

    // C++ Style
    int* p2 = new int; // int 사이즈 할당(4Byte)
    delete p2; // 

    int* p3 = new int[10]; // int 사이즈 배열 할당(4Byte * 10)
    delete[] p3; // new Array 타입으로 생성 시 delete[]로 해지
}
반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ Explicit Casting  (0) 2019.05.06
C++ reference 변수  (0) 2019.05.06
C++ 함수 특징 #2  (0) 2019.05.05
C++ 함수 특징 #1  (0) 2019.05.05
C++ 제어문(if, switch)과 반복문(for)  (0) 2019.01.16

반응형

Delete Function(명시적 삭제)

  • 특정 타입의 함수를 제공하지 않을 경우 인자 형변환으로 호환 가능한 함수를 호출함
  • 특정 타입의 함수를 선언만 하면 해당 함 수 사용시 링크 에러 발생
  • 해당 함수를 명시적 삭제(delete)하면 함수 사용시 컴파일 에러 발생
template<typename T>
T Square(T a)
{
    return a * a;
}

void Foo(int a) {}
void Foo(double a) = delete; // double 타입 파라미터 Foo 함수를 명시적 삭제

double Square(double) = delete; // 템플릿에서 double 타입만 제공하지 싶지 않을때

int main()
{
	Foo(3.4); // 명시적 삭제하지 않았을 경우 형변환 되어 Foo(int a) 함수가 실행됨
    Foo(3.4); // 명시적 삭제 상태일때는 컴파일 에러 발생(deleted function error)
    Square(3.4); // 템플릿 함수이지만 double 타입 함수는 삭제됨 에러 발생
}

 

Suffix Return Type

  • C++11 이상
  • 리턴 타입을 함수() 뒤에 적는 표기법
  • suffix return or trailing return 이라고 함
  • 원래의 리턴 값 위치에는 auto를 표기
  • 람다 표현식이나 함수 템플릿을 만들때 많이 사용
template<typename T, typename U>
auto Add(T a, U b) -> decltype(a + b) // 리턴타입이 함수 정의부 이후에 결정이 필요할 경우
{
    return a + b;
}

int main()
{
    Add(1, 2.2); // 템플릿 함수를 호출 시 인자 타입이 상이할 경우 템
}

 

Constexpr Function

  • C++11 이상
  • 함수 인자로 컴파일 시간에 결정될 수 있는 상수 값이 전달 될 경우 컴파일 시간에 연산을 수행하는 함수
  • 함수 인자가 컴파일 시간에 결정되는 상수가 아닌 경우 일반 함수와 동일하게 동작함
  • 함수 호출 구문을 배열의 크기나 템플릿 인자등 컴파일 시간 상수가 필요한 곳에서 사용 가능
  • 라이브러리 설계에서 많이 사용됨
constexpr int Add(int a, int b)
{
    return a + b;
}

int main()
{
    int n2 = Add(1, 2);
}
반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ reference 변수  (0) 2019.05.06
C++ new  (0) 2019.05.06
C++ 함수 특징 #1  (0) 2019.05.05
C++ 제어문(if, switch)과 반복문(for)  (0) 2019.01.16
C++ 변수의 특징(variable) #2  (0) 2019.01.15

반응형

Default Parameters

  • 함수 호출시 인자 전달을 생략하면 기본값이 적용된다.
  • 주의 사항
    • 함수의 마지막 파라미터부터 역순으로만 지정 가능
    • 헤더파일로 분리된 함수의 경우 선언에만 기본값을 정의 한다.(구현부
// 선언부, 구현부 분리 시 선언부에만 기본 파라미터 정의
void func1(int x, int y = 0, int z = 0);

// 구현부 가독성을 위해서 필요시 주석으로 표현
void func1(int x, int y /*= 0 */, int z /*= 0 */)
{
}

int main()
{
    func1(1, 1, 1); // 파라미터 기본값 사용 안함
    func1(1, 1); // 파라미터 기본값 z 사용
    func1(1); // 파라미터 기본값 y, z 사용
}

 

Function Overloading

  • 인자의 개수나 타입이 다르면 동일 이름의 함수를 2개 이상 만들 수 있음
  • 사용자 입장에서 일관된 함수를 제공 가능
  • 주의사항
    • 디폴트 값이 있는 함수에서는 주의 필요
    • 리턴 타임만 다른 경우는 오버로딩 불가
int square(int a)
{
    return a * a;
}

double square(double a)
{
    return a * a;
}

int main()
{
    square(1); // 정수 파라미터 함수 호출
    square(1.1); // 실수 파라미터 함수 호출
}

 

Inline Function

  • 함수 호출 시 실제 함수로 이동하지 않고 함수의 기계어 코드로 치환함
    • 장점 : 빠름
    • 단점 : 치환되는 함수가 클 경우 목적코드(실행파일)이 커질 수 있음
  • 인라인 상태 확인 방법
    • cl : 이름.cpp /FAs /Ob1 -> 이름.asm
    • g++ : 이름.cpp -S -02 -> 이름.s
  • 헤더파일에 구현부를 제공하여야 함
int add1(int a, int b)
{
    return a + b;
}

inline int add2(int a, int b)
{
    return a + b;
}

int main()
{
    int a = 1, b = 2;
    int n1 = add1(a, b); // 어샘블리어로 변환 시 함수 호출
    int n2 = add2(a, b); // 어샘블리어로 변환 시 함수자체로 치환
}

 

Template Function

  • 실제 함수가 아닌 함수를 만들어 내는 틀(template)
  • 사용자가 템플릿을 호출하는 코드를 보고 컴파일러가 필요한 타입의 함수를 생성
  • 템플릿 인자 표기는 "typename" 또는 "class"를 사용
  • 함수 뿐 아니라 구조체(or 클래스)도 템플릿으로 만들수 있음
  • 잘못 사용시 코드 메모리가 커질 수 있음(Code Bloat 현상)
// 함수를 만들어 내는 틀
template<typename T>
T square(T a)
{
    return a * a;
}

int main()
{
    square<int>(3); // int square(int) 함수 생성
    square<double>(3.3); // double square(double) 함수 생성
    
    square(3); // 생략시 타입 추론으로 int square(int) 함수 생성
    square(3.3); // 생략시 타입 추론으로 double square(double) 함수 생성
}
template<typename T>
struct Point
{
    T x;
    T y;
};


int main()
{
    Point<int> p1; // 멤버가 int인 Point 구조체 생성
    p1.x = 3;

    Point<double> p2; // 멤버가 double인 Point 구조체 생성
    p2.x = 3.3;
}
반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ new  (0) 2019.05.06
C++ 함수 특징 #2  (0) 2019.05.05
C++ 제어문(if, switch)과 반복문(for)  (0) 2019.01.16
C++ 변수의 특징(variable) #2  (0) 2019.01.15
C++ 변수의 특징(variable) #1  (0) 2019.01.14

반응형

C++11 for 문

  • Java, C#의 foreach()와 유사함
  • STL(C++ 표준 라이브러리)의 list, vector 등의 컨테이너 사용가능
  • 사용자 정의 list도 사용가능(추가 작업 필요)
#include <iostream>
int main()
{
    int x[5] = { 1,2,3,4,5 };

    // C++11 for
    for ( int n : x )
    {
        std::cout << n << std::endl;
    }

    // C++11 for
    for ( auto n : x ) // 편하게 auto 권장
    {
        std::cout << n << std::endl;
    }

    // C++11 하위 for
    for (int i = 0; i < 10; i++)
    {
        std::cout << n << std::endl;
    }

}


C++17 if init, switch init, if constexpr

  • 조건문(if, switch)에 초기화 구문을 포함 가능
  • if( 초기화문; 조건문 ), switch( 초기화문; 조건문 )
  • if constexpr( 컴파일 시간 조건문 ), 컴파일 시간의 상수 조건만 확인 가능, 템플릿 프로그래밍에서 
#include <iostream>
int main()
{
    // C++17 if
    if ( int result = foo(); result == 1) { }

    // C++17 switch
    switch( int result = foo(); result ) { }

    // C++17 if constexpr
    constexpr int a = 1;
    if constexpr ( a == a) { }

    // 이전 if
    int result = foo();
    if ( result == 1 ) {}

    // 이전 switch
    int result = foo();
    switch( result ) {}
}


반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ 함수 특징 #2  (0) 2019.05.05
C++ 함수 특징 #1  (0) 2019.05.05
C++ 변수의 특징(variable) #2  (0) 2019.01.15
C++ 변수의 특징(variable) #1  (0) 2019.01.14
C++ 표준 입출력(Basic Input/Output)  (1) 2019.01.13

반응형

C++ 상수를 만드는 방법

  • const : 초기값으로 literal뿐 아니라 변수도 사용 가능하다.
  • constexpr : 컴파일 시간 상수, 초기값으로 컴파일 시간에 결정된 값만 사용해야 한다. // C++11
  • 컴파일 타임 상수는 constexpr을 사용하자.
int main()
{
    int n = 10;

    const int c1 = 10;    // OK(컴파일타임 상수)
    const int c2 = n;    // OK(런타임 상수)

    constexpr int c1 = 10;    // OK(컴파일 타임 상수)
    constexpr int c2 = n;    // Error(런타임 상수는 불가)
}

 

C++ 문자열(STL string)

  • string 타입을 사용하자.(STL의 string 클래스)
    • 문자열 처리가 정수형 변수 처럼 직관적으로 사용 할 수 있다.
    • C언어의 const char*로의 변환이 필요하면 .c_str()을 사용한다.
  • C언어에서는 문자열
    • char* 또는 char 배열 사용
    • 복사 및 비교를 위해서는 문자열 전용 함수를 사용
#include <iostream>
#include <string.h>
#include <string>

int main()
{
    // C Style
    char s1[] = "hello";
    char s2[10];

    strcpy(s2, s1);
    if(strcmp(s2, s1) == 0)
    {
    }

    // C++ STL
    std::string s1 = "hello";
    std::string s2;
    
    s2 = s1; // C언어 strcpy(s2, s1) 동일
    if (s1 == s2) // C언어 strcmp(s2, s1) == 0 동일
    {
    }
    
    std::string s3 = s1 + s2;
    std::cout << s3 << std::endl;
}

 

C++ 구조체 바인딩(Structure binding) // C++17

  • 구조체 또는 배열의 각 멤버에서 값을 꺼낼때 사용
  • 타입은 반드시 auto를 사용해야 한다.

struct Point

{

int x = 10;

int y = 20;

};

 

int main()

{

Point p;

 

// 기존 Point 구조체의 멤버값을 복사

int a = p.x;

int b = p.y;

 

// Structure binding을 이용 복사(구조체)

auto [a, b] = p;

 

// Structure binding을 이용 복사(배열도 가능, 배열의 아이템 수가 일치해야 함)

int x[2] = { 1,2 };

auto[a,b] = x;

}

 

 

반응형

+ Recent posts