Thread: Book recommendation, Modern C++

  1. #1
    Registered User
    Join Date
    Nov 2018
    Posts
    30

    Book recommendation, Modern C++

    Hi all,

    I have finsihed the C book ( Sams teach yourself C in 21 days, old revision). it's a nice book. I am not a beginner but also not an expert.
    i also want to start learning C++.

    However i often hear terms like, Modern C++, effective C++, C++11/14...i don't want to learn in an very old book..

    Can you please recommend me some good books ?

    Thanks in advance

  2. #2
    Registered User catacombs's Avatar
    Join Date
    May 2019
    Location
    /home/
    Posts
    81
    Moden C by King is a great book. I've been going through it since the beginning of the year, and I've learned a lot. There are plenty of exercises and examples available. You can skip most of the beginning of the book if you already have the C basic down.

  3. #3
    Registered User
    Join Date
    May 2019
    Posts
    214
    For C++, any recent book by Stroustrup, Meyers or Sutter will be among the most authoritative.

    The terms you listed are also titles from these authors.

    The C++ language underwent a major update in 2011, hence the C++11 reference. The previous update was in 2003, a long stretch. Since C++11, the committee in charge of the official language specifications dedicated themselves to the goal of more frequent but smaller updates, which is the origin of the C++14 and C++17 standards. The upcoming C++20 (sometimes called C++2a for early and partial implementations) will be a little more substantial because several ideas intended for C++17 were delayed so that they would be more complete.

    As such, in 2019, "Modern" C++ is generally considered anything from C++11 forward, though many will focus on C++14 and C++17. The latter two have fewer language feature additions, some of which are quite useful and preferable, but fortunately they're also a much smaller subject and more easily adopted.

    The entire notion is that newer features not only take time to implement in the compilers, but for professionals to adopt them while the entire history of libraries and applications will still be valid C++ code from older versions of the language. It is, therefore, designed to be forward compatible. It is necessary to be able to compile code from older standards while incorporating new language features going forward (no one re-writes older code merely to comply with the newer standards).

    This also means that what someone knows from pre-C++11 is applicable, and tends to offer newer ways of writing which are either safer, more efficient or shorter to write.

    The study does naturally divide in two parts, and I've made points about the language itself. The second part is the standard library. The content and depth of the standard library has expanded greatly over the years, and references (good ones) show which features features are new.

    One thing you do not want to do is to focus on C++20 at this point. Compilers barely implement a few example features of that new standard. Even C++ 17 is considered new enough that documentation may warn that C++17 feature implementation should be considered fluid, and they do not guarantee that such features will be absolutely stable. It isn't likely, so people do use C++17 features, but it is possible that some implementation flaw may be discovered which could break C++17 code that happens to take advantage of a compiler quirk.

    Some books released relative to C++11 are still quite valid, so don't ignore them if they're from well regarded authors. Just check to see if (and when eventually) a more recent edition is published.

    Stroustrup's introductory work "C++ Principles and Practice" declares itself to be applicable to C++11/C++14. I don't know of a more recent update for C++17, but even if there were the book would barely change. It is an elementary to intermediate text Stroustrup used and intended for teaching.

    Some of the differences in the language from pre C++11/C++14 to modern C++ are minor but useful. A few (but by no means complete) examples:

    "auto" declarations. Like C, C++ did not have any automatic type creation, which other languages implemented as var. Those languages allowed the automatic creation of a type using var, instead of explicitly declaring a new variable as an int, double or more complex custom type (structs, templates, etc). The keyword "auto" was brought to the C++ language, and was humorously described as "var spelled a-u-t-o".

    In C++ some types are difficult to spell out correctly, because they're made of templates of templates, or otherwise just aren't very obvious, and on some occasions there are implied conversions available the programmer might not realize which happen by accidentally choosing some slightly varied wording of the type. This is a more complex version of the automatic conversions you expect from a double assigned to an int. "Auto" all but eliminates both the burden of getting complex types correct, but of ensure the type being used is correct.

    "Modern" (post C++11) loops have changed. The typical "for" loop works as it always has from it's C roots. There's no reason not to use them when appropriate, or to stop and try to think about the newer style(s). There is one use case, however, that was a source of bugs, and that's when sequencing through a container or array. One might write

    Code:
    for( int i = 0; i < c.size(); ++ i )
    {
     c[ i ] = ......
    }
    Where c is some type of container, like vector.

    This should work well in part because "size" comes directly from the container and should be correct. When that comes from some other variable there have been known cases where bugs are found simply because the limit was wrong, and the loop runs off the end of the container.

    The "new" style does this:

    Code:
    for( auto & p : c )
    {
     p = .....
    }
    Here, auto selects the type of the element from the container c automatically. Whatever "c" contains, auto will correctly reference. There is no "i" here. There's no need to use "c[i]", and no concern for the end of the container. This is a "safer for loop" for a container, and also a safer way to reference each element in the container.

    I show these two to illustrate the evolutionary nature of the differences you'll find moving from the various versions of C++ from 11 forward.

    One more important feature deals with references in C++. In C one finds the use of a "pointer to a pointer", usually passed as the address of a pointer, to allow functions to alter a pointer used by calling code. For a long while, C++ used a reference for this purpose, and reference applies to non pointer types. In C, for a function to be able to change an integer (or other simple type) owned by the calling code, one passes the address of the integer where the function takes the pointer to an integer. For C++, this is replaced by the reference, and the programmer no longer thinks in terms of pointers (or pointers to pointers) in such situations. A function declaration like void foo( int & i ); shows how a reference is declared, using the "&" operator, which C only used for "the address of" a value. Calling "foo" with an integer "n" is merely foo( n ); Where the function is declared to accept a reference, the function will be able to change the content of "n" visible and persistent to the calling code, must like C's pointer to an integer pattern.

    However, this comes to an interesting problem in more advanced work, especially for templates. Eventually there comes a question where a reference to a reference (a counterpoint to the pointer to a pointer) comes up, as in "foo( int && i)". For over two decades there was no real answer as to what was the underlying meaning of a reference to a reference.

    In modern C++, this has been resolved, so a reference to a reference is just a reference, and now can be used for "perfect forwarding" of parameters in template code.

    There are several, some far more advanced notions, but since you're coming from C, I chose to focus on those you'll encounter early in the study and leave the meaty material to the books you read.

    By far the largest and deepest advancement to the language has been in the standard library content. The standard library of early C++ was more like C's standard library, which was before templates were added to C++.

    To a C programmer, templates are a completely new notion. A type can be fashioned (usually as a class or struct, but also as a function) which takes parameters. The "swap" function is a typical example.

    std::swap is built as a template function. If swap is called with a pair of doubles, the compiler generates a version of swap for doubles. If it is called for a pair of struct pointers, the compiler generates a swap function for a pair of struct pointers.

    This was the origin of the "STL", originally from HP. From the STL we gained containers, like vector or map (or the underused deque). They are instantiated with a type, like:

    Code:
    vector< double > s;
    Which fashions the code for vector to operate on doubles.

    The "Boost" library introduced a number of advancements along the way, and among them were smart pointers (shared_ptr). This eventually made its way into the C++ language standard.

    There was a serious "mistake" along the way. You may find reference to "auto_ptr", a smart pointer template class. This has been deprecated, and replaced with "unique_ptr" and "scoped_ptr". The original design of "auto_ptr" had a few serious flaws, now corrected with "unique_ptr" and "scoped_ptr".

    Such mistakes are exceedingly rare, but if you find a text which refers to and uses "auto_ptr", just remind yourself that is now "unique_ptr" in most cases, "scoped_ptr" in some few cases.

    If you find code from an older library, or older codebase, which uses "auto_ptr", it will likely not compile in newer compilers, which may require specific settings to get the code to compile. It is one of the very few situations were older code may be well re-factored to use newer C++ features (switching auto_ptr to unique_ptr), even if the older code seems to work well.

    The point in that winding road is to illustrate that books covering the standard library of modern C++ may well limit to C++14 (or even C++11), and are still valid, but you'll find as you refer to the formal documentation newer versions of the feature listed.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Scatman
    However i often hear terms like, Modern C++, effective C++, C++11/14...i don't want to learn in an very old book..

    Can you please recommend me some good books ?
    Unfortunately the formerly best book for learning standard C++, Accelerated C++, is indeed an old book that hasn't been updated by Koenig and Moo for C++11. That said, if it's available at your local library, it could still be an option in conjunction with newer material for C++11 and later (e.g., Effective Modern C++), except that you'll end up unlearning quite a few things with that route.

    For a more updated book, though not quite utilising the teaching approach Koenig and Moo tried in real life classes and Stroustrup recommended, my browsing of C++ Primer, 5th Edition leads me to say that it is a good introductory book. However, take care to obtain the 5th Edition (earlier editions don't cover C++11), and to ensure that it is by Lippman, Lajoie, and Moo as there is an inferior book with a similiar name by a different author.

    Quote Originally Posted by Niccolo
    However, this comes to an interesting problem in more advanced work, especially for templates. Eventually there comes a question where a reference to a reference (a counterpoint to the pointer to a pointer) comes up, as in "foo( int && i)". For over two decades there was no real answer as to what was the underlying meaning of a reference to a reference.

    In modern C++, this has been resolved, so a reference to a reference is just a reference, and now can be used for "perfect forwarding" of parameters in template code.
    Do you have a reference for this? (Spot the pun!) I have never heard of rvalue and universal references as being described as "reference to a reference", i.e., that the && syntax might look like a "reference to a reference" is mere coincidence (i.e., they had to pick some syntax, and since && is akin to &, and its other usage is non-conflicting like the other usage for &, it was chosen).
    Last edited by laserlight; 07-10-2019 at 05:45 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    May 2019
    Posts
    214
    Do you have a reference for this? (Spot the pun!) I have never heard of rvalue and universal references as being described as "reference to a reference",
    It's been years, but way back before C++11 when Boost was offering a "REF" macro for parameter forwarding, I had a book discussing boost which brought it up.

    The subject was what happened when forwarding parameters from template functions, like that of bind, and how to work around the problem.

    This was when the author (and I have no memory who) used that form "reference to a reference", which was discussing the issue of forwarding reference parameters in a template operating like bind.

    Stroustrup also wrote on the point, as did Meyers, before the universal reference was proposed for C++, but I don't know where the work is now. I'm not even sure if their contributions were in print or from the web, but it was not from lecture.

    Yet, the question came up in earlier, pre-C++03 discussions about forwarding references using templates, in which many would ask "what is a reference to a reference", which would happen if the supplied parameter were a reference in a function, being forwarded to a function that took a reference. That implied wrapping. It is simpler, and obvious, when an integer is forwarded as an integer reference, or a pointer is forwarded as a pointer reference, but that left to ask what happens when attempting to forward an integer reference as ..... a reference to an integer reference...hence, the phrase "reference to a reference".

    Imagine using bind to forward to a function that takes an int &, but what it to be supplied to the call when the bind is used will be an int &, such that what is being forwarded ends up being an reference to an integer reference. We were trying this back in the late 90's, and the compiler would balk.

    I was reading, around that era (perhaps 2001 or earlier, I don't recall) how the thinking was progressing to solve this in C++03, which was C++0x at the time, where either Meyers, Sutter or Stroustrup mentioned that after thought on the point, a reference to a reference is just a reference being forwarded, and the universal reference was under formulation but had not even been coined by that name yet.

    Naturally, the notion of "reference to a reference" is not commonly heard or written, though I'm convinced the "&&" is not mere accident or coincidence, as the origin of the problem was exactly that...forwarding a reference as a reference in code that would fashion the enigma automatically in template code, causing the compiler to blow up (hence boost's use of the "REF" macro - which worked by pointers, perhaps pointers to pointers or the address of references - I don't recall, as they were short lived and irrelevant now).

    I suspect you're well under 40 years old. This is the kind of "history" those of us 50 somethings (heavy on the something now) remember going through, and waiting for (like we're waiting for concepts now).

    The entire notion of universal references was a solution to this particular problem, because parameter forwarding of just about everything that is not a reference could be forwarded without issue pre-C++03. It was the reference that cause the problem in such parameter forwarding problems. Boost, and likely other authors and engineers, recognized this problem long before, and used macros to represent references to references using the REF macro, which substituted code (sometimes pointers to pointers, or what have you) to forward the references through something like bind. The use of that macro as since disappeared from use, and many who began the study of C++ past a certain time frame simply don't recall it was ever required, or never used these types of templates where it came up to notice it.
    Last edited by Niccolo; 07-10-2019 at 06:13 PM.

  6. #6
    Registered User
    Join Date
    Nov 2018
    Posts
    30
    Hi all,

    Thanks a lot for your replies.

    @Catacombs : sounds good but coudnt find it, do you have a link for that book ?

    @Niccolo : a great explanation with examples, just perfect, thanks alot.

    @laserlight : i got the book "my browsing of C++ Primer" , will start with it very soon , thanks a lot

  7. #7
    Registered User I C everything's Avatar
    Join Date
    Apr 2019
    Posts
    101
    whats the best book containing abstract (tree I seen in this forum) exercises for one that are used to more lowlevel solutions,Cooper meantioned some book he got the tree exercise from
    but also want to find book about vectors
    you tell me you can C,why dont you C your own bugs?

  8. #8
    Registered User
    Join Date
    May 2019
    Posts
    214
    @laserlight,

    It took a while, but I found something. This is not the actual text I read back in the day (but it was very similar), but Meyers (one of those I mentioned) uses this phrase here: Universal References in C++11—Scott Meyers :

    Standard C++
    , scroll down to the section entitled "Nitty Gritty Details"

    Here are some excerpts:

    Nitty Gritty Details

    The true core of the issue is that some constructs in C++11 give rise to references to references, and references to references are not permitted in C++. If source code explicitly contains a reference to a reference, the code is invalid:


    • Widget w1;
    • ...
    • Widget& & w2 = w1; // error! No such thing as “reference to reference”

    There are cases, however, where references to references arise as a result of type manipulations that take place during compilation, and in such cases, rejecting the code would be problematic. We know this from experience with the initial standard for C++, i.e., C++98/C++03.

    .......

    Because of the reference-to-reference, this instantiated code is prima facie invalid, but the source code– “f(x)” – is completely reasonable. To avoid rejecting it, C++11 performs “reference collapsing” when references to references arise in contexts such as template instantiation.
    This appears to be dated from 2011/2012, and he's remembering what they discussed on this issue in '98.

    I remember living through this era as a developer, and Stroustrup was still the only source for C++, C++98 had not been released but Stroustrup had announced he was handing the torch over to a public committee so the language would go on without him, no matter what.

    It was exactly this "reference to a reference" formation that came from template code (exampled in some bind like creations), where a "reference to a reference" would blow up the compiler (often causing segmentation faults).

    In that era, 64 Mbytes of RAM was over $2000 (that's Mbytes, not Gbytes), and the compilers were relatively primitive. Many were still using the 486 CPU, and the Penitum 90 was new.

    I could swear it was boost, but perhaps I simply remember the "REF" macro being used to appease early boost versions, where this issue came up.

    I submit that the "&&" is not coincidence. The origin of the problem, of the question itself, of the solution eventually proposed, was, indeed, as Meyers remembers, initially brought forward from the reference to a reference problem.

    Hardly anyone wrote code by hand which caused the problem. It just never came up. It happened when code was generated from templates, and then we could contrive non-template examples that wouldn't compile.

    The notion of reference collapsing, of the underlying meaning of what a reference to a reference really was (it had no definition, Stroustrup, I remember, considering an oversight from the first implementation of templates), are at the origin of what eventually became universal references.
    Last edited by Niccolo; 07-11-2019 at 02:18 PM.

  9. #9
    Registered User
    Join Date
    May 2019
    Posts
    214
    @laserlight,

    After reading Meyer's replies on the linked page, I now come to see Meyers is the origin of the term "Universal References", and they were not called that when the notions of reference collapsing, rvalue and lvalue references were implemented. He coined the term to help explain them, but it seems to be his invention for discussion and teaching, not exactly the formal name.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Niccolo View Post
    @laserlight,

    After reading Meyer's replies on the linked page, I now come to see Meyers is the origin of the term "Universal References", and they were not called that when the notions of reference collapsing, rvalue and lvalue references were implemented. He coined the term to help explain them, but it seems to be his invention for discussion and teaching, not exactly the formal name.
    The formal names are "lvalue reference" and "rvalue reference"

    Universal references don't exist in the semantics of C++, but rather is useful to refer to syntax involving && with some deduced type before it that could be interpreted either way.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User catacombs's Avatar
    Join Date
    May 2019
    Location
    /home/
    Posts
    81
    Quote Originally Posted by Scatman View Post
    @Catacombs : sounds good but coudnt find it, do you have a link for that book ?
    I didn't notice this thread was about C++ book recommendations. I read it as regular C.

    Regardless, the C book I talked about is C Programming: A Modern Approach - Second Edition.

    For C++, I'd second Accelerated C++. I'm reading through the book and am enjoying it.

  12. #12
    Registered User
    Join Date
    Nov 2018
    Posts
    30
    Quote Originally Posted by catacombs View Post
    Seems to be a good book, but too expensive ..will check in a library

    Accelerated C++ and my browsing of C++, i have now...hopefully i will enjoy them aslo

    thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Book recommendation C
    By nutzu2010 in forum C Programming
    Replies: 6
    Last Post: 01-09-2011, 02:57 AM
  2. Book recommendation
    By belhifet in forum C# Programming
    Replies: 5
    Last Post: 04-12-2007, 11:45 AM
  3. book recommendation
    By kermit in forum C Programming
    Replies: 3
    Last Post: 08-30-2003, 12:09 PM
  4. book recommendation
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 05-03-2002, 11:48 PM
  5. Book Recommendation
    By Generator in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 11-05-2001, 09:42 PM

Tags for this Thread