Possibly learning old C++ standard

Viewed 218

I am interested in learning C++, and I found a book that seems to be the right fit for me. However, even though the book is quite new, some readers criticized that an earlier version of the book did not really dive into the new C++ standards (such as C++11, C++14, C++17) and rather used the "old C++ standard" (i.e., pre C++11).

While I checked if the newer version covered the new aspects of C++11 etc. (and it seemed like it covered quite a few), I am uncertain if possibly learning a pre C++11 standard would be inefficient? It seems like the new version does covers the new C++ standards (C++11 and upwards), but let's assume it does not. Would the knowledge I gain be outdated?

Again, I am new to C++, so I am not sure if the newer C++ standards completely changed the language, possibly removing/changing (integral) parts of the language which I would learn with this (possibly outdated) book. I just want to avoid learning (integral) parts of the language which are not used anymore or which are used differently nowadays (with the newer standards). However, if all the new C++ standards did was adding new features (but not removing/changing old features), I don't think learning from the book would be an issue since I could simply learn the newer features afterwards.

So in what ways did the newer C++ standards change the language, and would you say learning from a possibly outdated book is an issue?

1 Answers

Some code have changed in C++11, main changes, IMO, are:

  • way to "return" big object:

    • Pre-C++11, it has been recommended to use output parameter to avoid copy:
    void MakeVector(std::vector<int>& v) {
        v.clear();
        // fill v;
    }
    
    • Since C++11, no longer required for movable types, and return by value is the way to go:
    std::vector<int> MakeVector() {
        std::vector<int> v;
        // fill v;
        return v;
    }
    
  • way to iterate container:

    • Pre-C++11, it would be a mix between index and iterator way:
    void Foo(std::vector<int>& v) {
        for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) { /* *it ..*/ }
    
        for (std::size_t i = 0; i != v.size(); ++i) { /* v[i] ..*/ }
    }
    
    • Since C++11, it is shorter (and optimal (end() is computed only once)):
    void Foo(std::vector<int>& v) {
        for (int& e : v) { /* ..*/ }
    }
    
  • way to write types:

    • Pre-C++11, type should be explicitly written:
    void Foo(std::vector<int>& v) {
        std::vector<int>::iterator it = std::find(v.begin(), v.end(), 42);
        // ...
    }
    
    • Since C++11, type can be deduced:
    void Foo(std::vector<int>& v) {
        auto it = std::find(v.begin(), v.end(), 42);
        // ...
    }
    
  • way to create predicate:

    • Pre-C++11, predicate should be done outside of the function as function or class:
    bool less_than_42(int i) { return i < 42; }
    
    struct less_than_x {
        less_than_x(int x) : x(x) {}
        bool operator()(int i) const { return i < x; }
        int x;
    };
    
    void Foo(std::vector<int>& v, int x) {
        std::vector<int>::iterator it1 = std::find_if(v.begin(), v.end(), less_than_42);
        std::vector<int>::iterator it2 = std::find_if(v.begin(), v.end(), less_than_x(x));
    
        // ...
    }
    
    • Since C++11, lambda simplify stuff (dedicated function might still be useful to avoid to duplicate lambda though):
    void Foo(std::vector<int>& v, int x) {
        auto it1 = std::find_if(v.begin(), v.end(), [](int e){ return e < 42; });
        auto it2 = std::find_if(v.begin(), v.end(), [x](int e){ return e < x; });
        // ...
    }
    

There are other changes, but which less invalidate C++03 way to code.

Related