Modern_Effective_C - 8BitsCoding/RobotMentor GitHub Wiki

์ฐธ๊ณ ์‚ฌ์ดํŠธ์˜ ์„ค๋ช…์ด ์ •๋ง ์ข‹์Œ...

๋‚ด๊ฐ€ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๋ณ„๋„๋กœ ์ •๋ฆฌํ•จ.


Modern C++์— ๋„์ž…๋œ ๋ฌธ๋ฒ• ์ •๋ฆฌ

Effective Modern C++


Initializer list

// C++03
int arr[4] = {3, 2, 4, 5};

vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(4);
v.push_back(5);
// ๋งค๋ฒˆ ์ด๋ ‡๊ฒŒ ์„ ์–ธํ•˜๊ธฐ ๋ถˆํŽธ
vector<int> v = {3, 4, 1, 9};
// ๋‚ด๊ฐ€ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
#include <initializer_list>
class boVector {
    vector<int> m_vec;
public:
    beVector(const initializer_list<int>& v) {
        for(initializer_list<int>::iterator itr = v.begin(); itr != v.end(); ++itr)
            m_vec.push_back(*itr);
    }
}

boVector v = {0, 2, 3, 4};
boVector v2{0, 2, 3, 4};
// ์™„๋ฒฝํ•˜๊ฒŒ ๋™์ผํ•จ.

auto type

std::vector<int> vec = {2, 3, 4, 5};

// C++ 03
for(std::vector<int>::iterator it = vec.begin(); it != vec.end(); it++)
    m_vec.push_back(*it);

// C++ 11
for(auto it = vec.begin(); it != vec.end(); it++) 
    m_vec.push_back(*it);

foreach

// C++ 03
for(vector<int>::iterator itr = v.begin(); itr != v.end(); itr++)
    cout << (*itr);

// C++ 11
for(int i : v) {
    cout << i;
}

for(auto& i : v) {
    i++;
}

nullptr

void foo(int i) { cout << "foo_int" << endl; }
void foo(char * pc) { cout << "foo_char*" << endl; }

int main() {
    // C++03
    foo(NULL);      // Ambiguity(๋ชจํ˜ธ)

    // C++11
    foo(nullptr);   // call foo(char*)
}

enum class

// C++ 03
enum apple {green_a, red_a};
enum orange {big_o, small_o};
apple a = green_a;
orange o = big_o;

if (a == o)
    cout << "์˜ค๋ฅ˜"
else
    cout << "์ •์ƒ"
// C++ 11
enum class apple {green, red};
enum class orange {big, small};
apple a = apple::green;
orange o = orange::big;

static_assert

// run-time assert
assert(myPointer != NULL)

// Compile time assert(C++11)
static_assert(sizeof(int) == 4);

Delegating Constructor

class dog {
public:
    dog() { ... }
    dog(int a) { dog(); doOtherThings(a); }
};

// C++ 03
class dog {
    init() { ... };
public:
    dog() { init(); }
    dog(int a) { init(); doOtherTings(); }
};
// C++ 11
class dog {
public:
    dog() { ... }
    dog(int a) : dog() { doOtherTings(); }
};

Override (for virtual function)

// C++ 03
class dog {
    virtual void fn_A(int);
    virtual void fn_B() const;
};

class yellowdog : public dog {
    virtual void fn_A(float);      // ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋จ
    virtual void fn_B();           // ์—ญ์‹œ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋จ
};
// C++ 11
class dog {
    virtual void fn_A(int);
    virtual void fn_B() const;
    void fn_C();
};

class yellowdog : public dog {
    virtual void fn_A(float) override;      // Error(no function to override)
    virtual void fn_B() override;           // Error
    void fn_C() override;                   // Error
};

final

class dog final {
    // no class can be derived from dog
};

class dog {
    virtual void bark() final;
    // No class can override bark()
}

Compiler Generated Default Constructor

// C++ 03
class dog {
    dog(int age) {}
};

dog d1;     // Error (compiler will not generate the default constructor)
// C++ 11
class dog {
    dog(int age);
    dog() = defualt;
};

delete

// C++ 03
class dog {
    dog(int age) {}
};

dog a(2);
dog b(3.0);     // 3.0 is converted from double to int
a = b;          // Compiler generated assignment operator
// C++ 11
class dog {
    dog(int age) {}
    dog(double) = delete;
    dog& operator=(const dog&) = delete;
};

constexpr

int arr[6];
int A() { return 3; }
int arr[A() + 3];       // Compile Error

// C++11
constexpr int A() { return 3; }
// Force the computation to happen at compile time.

int arr[A()+3];
// Create an array of size 6

// Write faster program with constexpr
constexpr int cubed(int x) { return x * x * x; }

int y = cubes(1789);
// computed at compile time

New String Literals

// C++ 03
char * a = "string";

// C++ 11
char * a = u8"string";       // to define an UTF-8 string
char16_t * b = u"string";    // to define an UTF-16 string
char32_t * c = U"string";    // to define an UTF-32 string
char * d = R"string \\";        // to define raw string.

(์ฐธ๊ณ ) UTF-8 : ์œ ๋‹ˆ์ฝ”๋“œ๋ฅผ ์œ„ํ•œ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜

ํ•œ ๋ฌธ์ž๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด์„œ 1~4bytes๊นŒ์ง€๋ฅผ ์‚ฌ์šฉ

(์ฐธ๊ณ 2) ์œ ๋‹ˆ์ฝ”๋“œ vs ๋ฉ€ํ‹ฐ๋ฐ”์ดํŠธ :

์œ ๋‹ˆ์ฝ”๋“œ - ์•„์Šคํ‚ค ์ฝ”๋“œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ•œ๊ธ€, ์ผ์–ด๋“ฑ์„ ๋ชจ๋‘ ํ•œ ๋ฌธ์žํ‘œ๋กœ ํ‘œํ˜„

๋ฉ€ํ‹ฐ๋ฐ”์ดํŠธ - ์•„์Šคํ‚ค ์ฝ”๋“œ ๋ฌธ์žํ‘œ์— ์ถ”๊ฐ€ํ•˜์—ฌ ๋‹ค๋ฅธ ๋ฌธ์žํ‘œํ˜„


lambda function

cout << [](int x, int y{return x+y}(3,4)) << endl;
// Output : 7

auto f = [](int x, int y){return x+y;};
cout << f(3, 4) << endl;
// Output : 7 

ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

template<typename func>
void filter(func f, vector<int> arr) {
    for(auto i : arr) {
        if(f(i))
            cout << i << " ";
    }
}

int main() {
    vector<int> v = {1, 2, 3, 4, 5, 6};

    filter([](int x) {return (x>3);}, v);           // Output: 4 5 6
    filter([](int x) {return (x>2 && x<5);}, v);    // Output : 3 4

    int y = 4;
    filter([&](int x) {return (x>y);}, v);
    // Output : 5 6
    // Note : [&] tells compiler that we want variable capture(lambda can access local variable)
}

Rvalue Reference

  1. Moving semantics
  2. Perfect forwarding
// What is rvalue reference?
int main() {
    int a = 5;
    // a is a lvalue
    int& b = a;
    // b is a lvalue reference

    int&& c;
    // c is a rvalue reference
}
void printInt(int& i) {cout << "lvalue reference: " << i << endl;}
void printInt(int&& i) {cout << "rvalue reference: " << i << endl;}

int a = 5;
printInt(a);        // Call lvalue reference : printInt(int& i)
printInt(5);        // Call rvalue reference : printInt(int&& i)
class boVector {
    int size;
    double * arr_;
public:
    boVector(const boVector& rhs) {
        size = rhs.size;
        arr_ = new double[size];
        for(int i = 0; i < size; i++) { arr_[i] = rhs.arr_[i]; }
    }
    ~boVector() {delete arr_;}
};

void foo(boVector v);
void foo_by_ref(boVector& v);

boVector createBoVector();  // Creates a boVector

void main() {
    boVector reuseable = createBoVector();
    foo(resuable);
    // Copy constructor๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

    foo_by_ref(createBoVector());
    // createBoVector()์˜ ๋ฆฌํ„ด์€ r-value์ด๋‹ค.
    // Move constructor๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
    // r-value์šฉ constructor๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
}
class boVector {
    int size;
    double * arr_;
public:
    boVector(const boVector& rhs) {
        size = rhs.size;
        arr_ = new double[size];
        for(int i = 0; i < size; i++) { arr_[i] = rhs.arr_[i]; }
    }
    boVector(const boVector&& rhs) {    // Move constructor
        size = rhs.size;
        arr_ = rhs.arr_;
        rhs.arr_ = nullptr;
    }
    ~boVector() {delete arr_;}
};

์ด๋ ‡๊ฒŒ ํ•˜๋Š” ์ด์œ ๋Š” ์ž˜ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์•Œ์ง€๋งŒ

l-value ๋ณต์‚ฌ๋Š” ๋งค๋ฒˆ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์žฌ ํ• ๋‹นํ•˜๋ฉฐ ์ž์›์˜ ์†Œ๋ชจ๊ฐ€ ์žˆ๋Š” ๋ฐ˜๋ฉด r-value ๋ณต์‚ฌ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์žฌ ํ• ๋‹นํ•˜์ง€ ์•Š๊ณ  ์žฌํ™œ์šฉํ•˜๊ธฐ์— ์ž์›์˜ ์†Œ๋ชจ๊ฐ€ ๋œ ํ•˜๋‹ค.


โš ๏ธ **GitHub.com Fallback** โš ๏ธ