How to set up smartphones and PCs. Informational portal

Effective use in 55 sure ways.

Name: Best Uses for C ++ - 35 New Best Practices for Improving Your Programs and Projects.

The book, which is a continuation of the popular edition of Effective C ++, you can learn how to use the constructions of the C ++ language most efficiently, as well as consider ways of casting types, the implementation of the RTTI mechanism, operator overloading rules, etc. The book provides recommendations on the use of smart pointers, virtual constructors, the buffered new operator, proxy classes, and double dispatch. Special attention is paid to working with exceptions and the possibilities of using C code in programs written in C ++. The latest features of the language are outlined in detail and presented how to increase the performance of programs with their help. Applications store the auto_ptr template code and an annotated list of C ++ references and Internet resources.


Content
Introduction. 14
Chapter 1. The basics. 23
Rule 1. Distinguish between pointers and links. 23
Rule 2. Prefer C ++-style casts. 25
Rule 3. Never use polymorphism on arrays. thirty
Rule 4. Avoid unnecessary default constructors. 33
Chapter 2. Operators. 38
Rule 5. Beware of UDFs. 38
Rule 6. Distinguish between the prefix and postfix forms of the increment and decrement operators. 45
Rule 7. Never overload the &&, 11, and operators. 48
Rule 8. Distinguish between the meaning of the operators new and delete. 51
Chapter 3. Exceptions. 57
Rule 9. To avoid leaking resources, use destructors. 58
Rule 10. Avoid leaking resources in constructors. 63
Rule 11. Do not propagate exception handling outside of the destructor. 71
Rule 12. Distinguish throwing an exception from passing a parameter or calling a virtual function. 73
Rule 13. Catch by-reference exceptions. 80
Rule 14. Use exception specifications wisely. 84
Rule 15. Estimate the cost of handling exceptions. 90
Chapter 4. Efficiency. 94
Rule 16. Don't forget the 80-20 rule. 95
Rule 17. Use lazy computation. 97
Rule 18. Reduce the cost of expected computations. 106
Rule 19. Investigate the causes of temporary objects. 110
Rule 20. Make it easy to optimize the return value. 113
Rule 21. Use overloading to avoid implicit type conversion. 116
Rule 22: Whenever possible, use an assignment operator instead of a separate operator. 118
Rule 23. Use different libraries. 121
Rule 24: Consider the costs associated with virtual functions, multiple inheritance, virtual base classes, and RTTI. 124
Chapter 5. Receptions. 134
Rule 25. Make virtual constructors and functions that are not members of the class. 134
Rule 26. Limit the number of objects in the class. 140
Rule 27: Require or deny heap allocation as appropriate. 154
Rule 28. Use smart pointers. 167
Rule 29. Use reference counting. 190
Rule 30. Use proxy classes. 218
Rule 31. Create functions that are virtual in relation to more than one object. 231
Chapter 6. Miscellanea. 254
Rule 32. Program for the future. 254
Rule 33. Make nonterminal classes abstract. 259
Rule 34. Know how to use an aqueous C and C ++ program. 270
Rule 35. Become familiar with the language standard. 276
Appendix 1. List of recommended literature. 284
Appendix 2. Implementation of the auto_ptr template.

Operators.
Overloaded operators should be treated with respect. They allow you to apply the same syntax to user-defined types as you would to built-in types, and also provide unheard of perspectives thanks to the functions behind these operators. But being able to make characters like + or - do whatever you want also means that overloaded operators can make programs completely incomprehensible. However, there are many skilled C ++ programmers who know how to harness the power of overloaded operators without turning a program into a black box.

It is unfortunately easy for the less skilful to make mistakes. Constructors with only one argument and implicit type conversion operators can be especially troublesome because their calls do not always match in source texts programs. This leads to the emergence of programs whose behavior is very difficult to understand. Another problem arises when overloading operators such as && and II, because the transition from built-in operators to user-written functions results in subtle changes in semantics that are easy to overlook. Finally, many operators relate to each other according to standard rules, and due to overloaded operators, generally accepted relations are sometimes violated.

In the rules that follow, I've tried to explain when and how overloaded operators are used, how they behave, how they should relate to each other, and how they can all be controlled. Once you have mastered the materials in this chapter, you will overload (or not overload) operators with the same confidence as a true professional.

Free download e-book in a convenient format, watch and read:
Download the book Making the most of C ++ - 35 new tips to improve your programs and projects - Meyers S. - fileskachat.com, fast and free download.

Download djvu
Below you can buy this book at the best discounted price with delivery throughout Russia.

Scott Meyers

Effective use of C ++. 55 surefire ways to improve the structure and code of your programs

Reviews of the third editionEffective use C ++

Scott Meyers book Using C ++ Effectively, Third Edition- is the concentration of programming experience - the experience that without it would have gotten you dearly. This book is an excellent resource that I recommend to anyone writing C ++ professionally.

Peter Dulimov, ME, Engineer, Evaluation and Research Unit, NAVSYSCOM, Australia

Third Edition remains the best book on how to put all the pieces of C ++ together to create efficient and consistent programs. If you are applying to be a C ++ programmer, then you should read it.

Eric Nagler, Consultant, Trainer and Author of Learning C ++

The first edition of this book was one of a small (very small) number of books that helped me to significantly improve my level as a professional software developer. Like other books in this series, it turned out to be practical and easy to read, but it also contained many important tips. "Effective use C ++ ", third edition, continues this tradition. C ++ is very powerful language programming. If C provides a rope to climb to the top of a mountain, then C ++ is a whole store where all kinds of people are ready to help you tie the knots on this rope. Mastering the material in this book will definitely increase your ability to use C ++ effectively without dying of stress.

Jack W. Reeves, Executive Director Bleading Edge Software Technologies

Each new developer who comes to my team, immediately gets the task - to read this book.

Michael Lancetta, Lead Software Engineer

I read the first edition of Effectively Using C ++ about 9 years ago, and this book immediately became one of my favorite C ++ books. In my opinion, the third edition of Effectively Using C ++ remains a must-read for anyone who wants to program effectively in C ++. We will live in a better world if C ++ programmers read this book before writing the first line of professional code.

Danny Rabbani, software engineer

The first edition of Scott Meyers' Effective Use of C ++ came to me when I was an average programmer and tried hard to do the best job I could. And that was salvation! I have found that Meyers' advice is practically helpful and effective, that it will 100% deliver what it promises. The third edition helps in the practical use of C ++ when working on modern serious software projects, providing information about the latest features and capabilities of the language. I discovered with pleasure that I could find a lot of new and interesting things for myself in the third edition of the book, which, as it seemed to me, I know very well.

Michael Topek, Technical Program Manager

This authoritative guide from Scott Meyers, a C ++ guru, is intended for anyone who wants to use C ++ safely and efficiently, or who is migrating to C ++ from any other object-oriented language. This book contains valuable information presented in a clear, concise, entertaining and insightful style.

Siddhartha Karan Singh, Software Developer

Acknowledgments

The book "Using C ++ Effectively" has been around for 15 years, and I started learning C ++ about 5 years before I wrote it. Thus, work on this project has been going on for about 20 years. During this time, I received wishes, comments, corrections, and sometimes overwhelming observations from hundreds (thousands?) Of people. Each of them contributed to the development of "Effective Use of C ++". I am grateful to all of them.

I have long given up trying to remember where and what I learned myself, but I cannot but mention one source, since I use it all the time. These are Usenet newsgroups, especially comp.lang.c ++. Moderated and comp.std.c ++. Many of the rules in this book (perhaps most) are the result of thinking about the technical ideas discussed in these groups.

Steve Dewhurst assisted me in selecting new material for the third edition of the book. Rule 11 takes the idea of ​​copy-and-swap implementation of operator = from Herb Sutter's notes, Problem 13 of his book Exceptional C ++ (Addison-Wesley, 2000). The idea of ​​grabbing a resource as initialization (rule 13) comes from The C ++ Programming Language (Addison-Wesley, 2002) by Bjarne Stroustrup. The idea behind Rule 17 is taken from the "Best practices" section of the Boost shared_ptr site (http://boost.org/libs/ smart_ptr / shared_ptr.htm # BestPractices) and refined based on the material in problem 21 in the book Herb Sutter, "More exceptional C ++" (Addison-Wesley, 2002). Rule 29 was inspired by Herb Sutter's extensive exploration of this topic in Exceptional C ++ Problems 8-19, More exceptional C ++ Problems 17-23 and Exceptional C ++ Problems 11-13. Style ”(Addison-Wesley, 2005). David Abrahams helped me better understand the three principles of making sure exceptions are safe. The non-virtual interface (NVI) idiom in Rule 35 is taken from Sutter's column "Virtuality" in the September 2001 C / C ++ Users Journal. The Template Method and Strategy design patterns mentioned in the same rule are taken from Design Patterns (Addison-Wesley, 1995) by Erich Gamma, Richard Helm, Ralph Johnson ( Ralf Johnson and John Vlissides. The idea for the NVI idiom in rule 37 came from Hendrik Schober. David Smallberg's contribution to the set implementation described in Item 38. The observation in Item 39 that optimization of an empty base class is fundamentally impossible with multiple inheritance is from David Vandevoorde and Nikolai M. Jossutis (Nickolai M. Josuttis) "Templates C ++" (Addison-Wesley, 2003). My initial idea of ​​what the typename keyword is in Rule 42 is based on the C ++ and C FAQ (http://www.comeaucomputing.com/techtalk/ #typename), which is endorsed by Greg Comeau, and Leor Zolman helped me realize that this view is wrong (my fault, not Greg's). The theme for rule 46 originated from Dan Saks' speech "How to Make New Friends." The idea at the end of rule 52 that if you declare one version of new, you must declare all the others, is outlined in problem 22 of Herb Sutter's Exceptional C ++. My understanding of the Boost review process (summarized in rule 55) was refined by David Abrahams.

Scott Meyers

Effective use of C ++. 55 surefire ways to improve the structure and code of your programs

Reviews of the third editionEffective use of C ++

Scott Meyers book Using C ++ Effectively, Third Edition- is the concentration of programming experience - the experience that without it would have gotten you dearly. This book is an excellent resource that I recommend to anyone writing C ++ professionally.

Peter Dulimov, ME, Engineer, Evaluation and Research Unit, NAVSYSCOM, Australia

Third Edition remains the best book on how to put all the pieces of C ++ together to create efficient and consistent programs. If you are applying to be a C ++ programmer, then you should read it.

Eric Nagler, Consultant, Trainer and Author of Learning C ++

The first edition of this book was one of a small (very small) number of books that helped me to significantly improve my level as a professional software developer. Like other books in this series, it turned out to be practical and easy to read, but it also contained many important tips. "Effective use C ++ ", third edition, continues this tradition. C ++ is a very powerful programming language. If C gives you a rope to climb to the top of a mountain, then C ++ is a whole store where all kinds of people are ready to help you tie the knots on that rope. Mastering the material in this book will definitely increase your ability to use C ++ effectively without dying of stress.

Jack W. Reeves, CEO, Bleading Edge Software Technologies

Every new developer who joins my team is immediately assigned the task of reading this book.

Michael Lancetta, Lead Software Engineer

I read the first edition of Effectively Using C ++ about 9 years ago, and this book immediately became one of my favorite C ++ books. In my opinion, the third edition of Effectively Using C ++ remains a must-read for anyone who wants to program effectively in C ++. We will live in a better world if C ++ programmers read this book before writing the first line of professional code.

Danny Rabbani, software engineer

The first edition of Scott Meyers' Effective Use of C ++ came to me when I was an average programmer and tried hard to do the best job I could. And that was salvation! I have found that Meyers' advice is practically helpful and effective, that it will 100% deliver what it promises. The third edition helps in the practical use of C ++ when working on modern serious software projects, providing information about the latest features and capabilities of the language. I discovered with pleasure that I could find a lot of new and interesting things for myself in the third edition of the book, which, as it seemed to me, I know very well.

Michael Topek, Technical Program Manager

This authoritative guide from Scott Meyers, a C ++ guru, is intended for anyone who wants to use C ++ safely and efficiently, or who is migrating to C ++ from any other object-oriented language. This book contains valuable information presented in a clear, concise, entertaining and insightful style.

Siddhartha Karan Singh, Software Developer

Acknowledgments

The book "Using C ++ Effectively" has been around for 15 years, and I started learning C ++ about 5 years before I wrote it. Thus, work on this project has been going on for about 20 years. During this time, I received wishes, comments, corrections, and sometimes overwhelming observations from hundreds (thousands?) Of people. Each of them contributed to the development of "Effective Use of C ++". I am grateful to all of them.

I have long given up trying to remember where and what I learned myself, but I cannot but mention one source, since I use it all the time. These are Usenet newsgroups, especially comp.lang.c ++. Moderated and comp.std.c ++. Many of the rules in this book (perhaps most) are the result of thinking about the technical ideas discussed in these groups.

Steve Dewhurst assisted me in selecting new material for the third edition of the book. Rule 11 takes the idea of ​​copy-and-swap implementation of operator = from Herb Sutter's notes, Problem 13 of his book Exceptional C ++ (Addison-Wesley, 2000). The idea of ​​grabbing a resource as initialization (rule 13) comes from The C ++ Programming Language (Addison-Wesley, 2002) by Bjarne Stroustrup. The idea behind Rule 17 is taken from the "Best practices" section of the Boost shared_ptr site (http://boost.org/libs/ smart_ptr / shared_ptr.htm # BestPractices) and refined based on the material in problem 21 in the book Herb Sutter, "More exceptional C ++" (Addison-Wesley, 2002). Rule 29 was inspired by Herb Sutter's extensive exploration of this topic in Exceptional C ++ Problems 8-19, More exceptional C ++ Problems 17-23 and Exceptional C ++ Problems 11-13. Style ”(Addison-Wesley, 2005). David Abrahams helped me better understand the three principles of making sure exceptions are safe. The non-virtual interface (NVI) idiom in Rule 35 is taken from Sutter's column "Virtuality" in the September 2001 C / C ++ Users Journal. The Template Method and Strategy design patterns mentioned in the same rule are taken from Design Patterns (Addison-Wesley, 1995) by Erich Gamma, Richard Helm, Ralph Johnson ( Ralf Johnson and John Vlissides. The idea for the NVI idiom in rule 37 came from Hendrik Schober. David Smallberg's contribution to the set implementation described in Item 38. The observation in Item 39 that optimization of an empty base class is fundamentally impossible with multiple inheritance is from David Vandevoorde and Nikolai M. Jossutis (Nickolai M. Josuttis) "Templates C ++" (Addison-Wesley, 2003). My initial idea of ​​what the typename keyword is in Rule 42 is based on the C ++ and C FAQ (http://www.comeaucomputing.com/techtalk/ #typename), which is endorsed by Greg Comeau, and Leor Zolman helped me realize that this view is wrong (my fault, not Greg's). The theme for rule 46 originated from Dan Saks' speech "How to Make New Friends." The idea at the end of rule 52 that if you declare one version of new, you must declare all the others, is outlined in problem 22 of Herb Sutter's Exceptional C ++. My understanding of the Boost review process (summarized in rule 55) was refined by David Abrahams.

All of the above concerns where and from whom I learned something, regardless of who first published the material on the relevant topic.

My notes also say that I used information from Steve Clamage, Antoine Trux, Timothy Knox and Mike Kaelbling, although unfortunately it is not specified where And How.

First edition drafts reviewed by Tom Cargill, Glenn Caroll, Tony Davis, Brian Kernigan, Jak Kirman, Doug Lea, Moises Lejter), Eugene Santos Jr. (Eugene Santos, Jr), John Shewchuk, John Stasko, Bjarne Stroustrup, Barbara Tilly and Nancy L. Urbano. In addition, suggestions for improvements that have been incorporated into later reissues were expressed by Nancy L. Urbano, Chris Treichel, David Corbin, Paul Gibson, Steve Vinoski, Tom Tom Cargill, Neil Rhodes, David Bern, Russ Williams, Robert Brazile, Doug Morgan, Uwe Steinmuller, Mark Somer (Mark Somer), Doug Moore, David Smallberg, Seith Meltzer, Oleg Steinbuk, David Papurt, Tony Hansen, Peter McCluskey ), Stefan Kuhlins, David Braunegg, Paul Chisholm, Adam Zell, Clovis Tondo, Mike Koelbling, Natraj Kini, Lars Numan, Greg Lutz, Tim Johnson, John Lakos, Roger Scott, Scott Frohman, Alan R ooks, Robert Poor, Eric Nagler, Anton Trucks, Cade Roux, Chandrika Gokul, Randy Mangoba and Glenn Teitelbaum.

Second Edition drafts reviewed by: Derek Bosch, Tim Johnson, Brian Kernighan, Junichi Kimura, Scott Lewandowski, Laura Michaels, David Smallberg, Clovis Tonado, Chris Van Wyk and Oleg Zabluda. Later runs have benefited from comments from Daniel Steinberg, Arunprasad Marathe, Doug Stapp, Robert Hall, Cheryl Ferguson, Gary Bartlett, Michael Bartl Tam Michael Tamm, Kendall Beaman, Eric Nagler, Max Hailperin, Joe Gottman, Richard Weeks, Valentin Bonnard, Jun He, Tim King, Don Mailer, Ted Hill, Marc Harrison, Michael Rubinstein, Marc Rodgers, David Goh, Brenton Brenton Cooper, Andy Thomas-Cramer, Anton Trucks, John Walt, Brian Sharon, Liam Fitzpatric, Bernd Mohr, Harry Yee (Gary Yee), John O "Hanley, Brady Paterson, Christopher Peterson (Christ opher Peterson, Feliks Kluzniak, Isi Dunetz, Christopher Creutzi, Ian Cooper, Carl Harris, Marc Stickel, Clay Budin ), Panayotis Matsinopulos, David Smallberg, Herb Sutter, Pajo Misljencevic, Giulio Agostini, Fredrik Blomqvist (Fredrik Blimqvist), Jensender Jensender Witold Kuzminski, Kazunobu Kuriyama, Michael Christensen, Jorge Yanez Teruel, Mark Davis, Marty Rabinowitz, Ares Lagae (Ares Lagae) and Alexander Medvedev.

Scott Meyers

Effective use of C ++. 55 surefire ways to improve the structure and code of your programs

Reviews of the third edition

Effective use of C ++

Scott Meyers book Using C ++ Effectively, Third Edition- is the concentration of programming experience - the experience that without it would have gotten you dearly. This book is an excellent resource that I recommend to anyone writing C ++ professionally.

Peter Dulimov, ME, Engineer, Evaluation and Research Unit, NAVSYSCOM, Australia

Third Edition remains the best book on how to put all the pieces of C ++ together to create efficient and consistent programs. If you are applying to be a C ++ programmer, then you should read it.

Eric Nagler, Consultant, Trainer and Author of Learning C ++

The first edition of this book was one of a small (very small) number of books that helped me to significantly improve my level as a professional software developer. Like other books in this series, it turned out to be practical and easy to read, but it also contained many important tips. "Effective use C ++ ", third edition, continues this tradition. C ++ is a very powerful programming language. If C gives you a rope to climb to the top of a mountain, then C ++ is a whole store where all kinds of people are ready to help you tie the knots on that rope. Mastering the material in this book will definitely increase your ability to use C ++ effectively without dying of stress.

Jack W. Reeves, CEO, Bleading Edge Software Technologies

Every new developer who joins my team is immediately assigned the task of reading this book.

Michael Lancetta, Lead Software Engineer

I read the first edition of Effectively Using C ++ about 9 years ago, and this book immediately became one of my favorite C ++ books. In my opinion, the third edition of Effectively Using C ++ remains a must-read for anyone who wants to program effectively in C ++. We will live in a better world if C ++ programmers read this book before writing the first line of professional code.

Danny Rabbani, software engineer

The first edition of Scott Meyers' Effective Use of C ++ came to me when I was an average programmer and tried hard to do the best job I could. And that was salvation! I have found that Meyers' advice is practically helpful and effective, that it will 100% deliver what it promises. The third edition helps in the practical use of C ++ when working on modern serious software projects, providing information about the latest features and capabilities of the language. I discovered with pleasure that I could find a lot of new and interesting things for myself in the third edition of the book, which, as it seemed to me, I know very well.

Michael Topek, Technical Program Manager

This authoritative guide from Scott Meyers, a C ++ guru, is intended for anyone who wants to use C ++ safely and efficiently, or who is migrating to C ++ from any other object-oriented language. This book contains valuable information presented in a clear, concise, entertaining and insightful style.

Siddhartha Karan Singh, Software Developer

Acknowledgments

The book "Using C ++ Effectively" has been around for 15 years, and I started learning C ++ about 5 years before I wrote it. Thus, work on this project has been going on for about 20 years. During this time, I received wishes, comments, corrections, and sometimes overwhelming observations from hundreds (thousands?) Of people. Each of them contributed to the development of "Effective Use of C ++". I am grateful to all of them.

I have long given up trying to remember where and what I learned myself, but I cannot but mention one source, since I use it all the time. These are Usenet newsgroups, especially comp.lang.c ++. Moderated and comp.std.c ++. Many of the rules in this book (perhaps most) are the result of thinking about the technical ideas discussed in these groups.

Steve Dewhurst assisted me in selecting new material for the third edition of the book. Rule 11 takes the idea of ​​copy-and-swap implementation of operator = from Herb Sutter's notes, Problem 13 of his book Exceptional C ++ (Addison-Wesley, 2000). The idea of ​​grabbing a resource as initialization (rule 13) comes from The C ++ Programming Language (Addison-Wesley, 2002) by Bjarne Stroustrup. The idea behind Rule 17 is taken from the "Best practices" section of the Boost shared_ptr site (http://boost.org/libs/ smart_ptr / shared_ptr.htm # BestPractices) and refined based on the material in problem 21 in the book Herb Sutter, "More exceptional C ++" (Addison-Wesley, 2002). Rule 29 was inspired by Herb Sutter's extensive exploration of this topic in Exceptional C ++ Problems 8-19, More exceptional C ++ Problems 17-23 and Exceptional C ++ Problems 11-13. Style ”(Addison-Wesley, 2005). David Abrahams helped me better understand the three principles of making sure exceptions are safe. The non-virtual interface (NVI) idiom in Rule 35 is taken from Sutter's column "Virtuality" in the September 2001 C / C ++ Users Journal. The Template Method and Strategy design patterns mentioned in the same rule are taken from Design Patterns (Addison-Wesley, 1995) by Erich Gamma, Richard Helm, Ralph Johnson ( Ralf Johnson and John Vlissides. The idea for the NVI idiom in rule 37 came from Hendrik Schober. David Smallberg's contribution to the set implementation described in Item 38. The observation in Item 39 that optimization of an empty base class is fundamentally impossible with multiple inheritance is from David Vandevoorde and Nikolai M. Jossutis (Nickolai M. Josuttis) "Templates C ++" (Addison-Wesley, 2003). My initial idea of ​​what the typename keyword is in Rule 42 is based on the C ++ and C FAQ (http://www.comeaucomputing.com/techtalk/ #typename), which is endorsed by Greg Comeau, and Leor Zolman helped me realize that this view is wrong (my fault, not Greg's). The theme for rule 46 originated from Dan Saks' speech "How to Make New Friends." The idea at the end of rule 52 that if you declare one version of new, you must declare all the others, is outlined in problem 22 of Herb Sutter's Exceptional C ++. My understanding of the Boost review process (summarized in rule 55) was refined by David Abrahams.

All of the above concerns where and from whom I learned something, regardless of who first published the material on the relevant topic.

My notes also say that I used information from Steve Clamage, Antoine Trux, Timothy Knox and Mike Kaelbling, although unfortunately it is not specified where And How.

First edition drafts reviewed by Tom Cargill, Glenn Caroll, Tony Davis, Brian Kernigan, Jak Kirman, Doug Lea, Moises Lejter), Eugene Santos Jr. (Eugene Santos, Jr), John Shewchuk, John Stasko, Bjarne Stroustrup, Barbara Tilly and Nancy L. Urbano. In addition, suggestions for improvements that have been incorporated into later reissues were expressed by Nancy L. Urbano, Chris Treichel, David Corbin, Paul Gibson, Steve Vinoski, Tom Tom Cargill, Neil Rhodes, David Bern, Russ Williams, Robert Brazile, Doug Morgan, Uwe Steinmuller, Mark Somer (Mark Somer), Doug Moore, David Smallberg, Seith Meltzer, Oleg Steinbuk, David Papurt, Tony Hansen, Peter McCluskey ), Stefan Kuhlins, David Braunegg, Paul Chisholm, Adam Zell, Clovis Tondo, Mike Koelbling, Natraj Kini, Lars Numan, Greg Lutz, Tim Johnson, John Lakos, Roger Scott, Scott Frohman, Alan R ooks, Robert Poor, Eric Nagler, Anton Trucks, Cade Roux, Chandrika Gokul, Randy Mangoba and Glenn Teitelbaum.

Second Edition drafts reviewed by: Derek Bosch, Tim Johnson, Brian Kernighan, Junichi Kimura, Scott Lewandowski, Laura Michaels, David Smallberg, Clovis Tonado, Chris Van Wyk and Oleg Zabluda. Later runs have benefited from comments from Daniel Steinberg, Arunprasad Marathe, Doug Stapp, Robert Hall, Cheryl Ferguson, Gary Bartlett, Michael Bartl Tam Michael Tamm, Kendall Beaman, Eric Nagler, Max Hailperin, Joe Gottman, Richard Weeks, Valentin Bonnard, Jun He, Tim King, Don Mailer, Ted Hill, Marc Harrison, Michael Rubinstein, Marc Rodgers, David Goh, Brenton Brenton Cooper, Andy Thomas-Cramer, Anton Trucks, John Walt, Brian Sharon, Liam Fitzpatric, Bernd Mohr, Harry Yee (Gary Yee), John O "Hanley, Brady Paterson, Christopher Peterson (Christ opher Peterson, Feliks Kluzniak, Isi Dunetz, Christopher Creutzi, Ian Cooper, Carl Harris, Marc Stickel, Clay Budin ), Panayotis Matsinopulos, David Smallberg, Herb Sutter, Pajo Misljencevic, Giulio Agostini, Fredrik Blomqvist (Fredrik Blimqvist), Jensender Jensender Witold Kuzminski, Kazunobu Kuriyama, Michael Christensen, Jorge Yanez Teruel, Mark Davis, Marty Rabinowitz, Ares Lagae (Ares Lagae) and Alexander Medvedev.

Early partial drafts of this edition were reviewed by: Brian Kernighan, Angelica Lunger, Jesse Lachley, Roger P. Pedersen, Chris Van Wyck, Nicholas Stroustrup and Hendrick Schober. The full draft was reviewed by: Leor Zolman, Mike Tsao, Eric Nagler, Zhenet Gutnik, David Abrahams, Gerhard Kreuser, Drosos Kouronis, Brian Kernigan, Andrew Crims, Balog Pal, Emily Jagdhar, Eugene Kalenkovich, Mike Rose, Benjko Carrarara, , Jack Reeves, Steve Shirippa, Martin Fallenstedt, Timothy Knox, Yoon Bai, Michael Lancetta, Philip Janert, Judo Bartholucci, Michael Topic, Jeff Scherpeltz, Chris Naurot, Nishant Mittal, Jeff Sommers, Hrendon Morungoff Lee, Jim Meehan, Alan Geller, Siddhartha Singh, Sam Lee, Sasan Dashinejad, Alex Martin, Steve Cai, Thomas Fruchterman, Corey Hicks, David Smallberg, Gunawardan Kakulapati, Danny Rabbani, Jake Cohen, Hendrik Schuber, Paco Wiziana, Glenn Jeffrey D. Oldham, Nicholas Stroustrup, Matthew Wilson, Andrei Alexandrescu, Tim Johnson, Leon Matthews, Peter Dulimov, and Kevlin Henney. Some individual paragraphs were also drafted by Herb Sutter and Attila F. Feher.

Reviewing a raw (and possibly incomplete) manuscript is difficult work, and having tight deadlines only makes it even more difficult. I am grateful to everyone who has expressed a desire to help me with this.

Viewing the manuscript is all the more difficult if you have no idea about the material, but should not miss none inaccuracies that could have crept into the text. It is amazing that there are people willing to edit texts. Christa Meadowbrook was the editor of this book and was able to identify many mistakes that everyone else has missed.

Leor Zolman checked all the code examples on various compilers during the manuscript review, and then did it again after I made the changes. If any mistakes remain, I am responsible for them, not Leor.

Karl Wigers and especially Tim Johnson wrote a short but useful cover text.

John Waite, editor of the first two editions of this book, inadvertently agreed to work in this capacity again. His assistant, Denise Mikelsen, invariably responded with a pleasant smile to my frequent and annoying remarks (at least I think so, although I have never personally met her). Julia Nahil "pulled out a short straw", she had to be in charge of the production of this book. For six weeks, she sat at night to keep up with her schedule without losing her composure. John Fuller (her boss) and Marty Rabinovich (her boss) were also directly involved in the preparation of the publication. Vanessa Moore's official duties were to layout the book in FrameMaker and create the PDF text, but she volunteered to add Appendix B and format it for printing on the inside cover. Solveig Hugland helped with the index. Sandra Schreueder and Chuti Praserzit were in charge of the cover design. It was Chuchi who had to redo the cover every time I said, "How about putting this photo in, but with a different color strip?" Chanda Lehry-Cooty was completely exhausted marketing the book.

For several months while I was working on the manuscript, the TV series Buffy the Vampire Slayer helped me relieve stress at the end of the day. It took a lot of effort to banish Buffy's talk from the pages of this book.

Katie Reed taught me programming in 1971, and I'm glad we remain friends to this day. Donald French hired Moses Lejter and me to develop C ++ tutorials in 1989 (which made me really learn C ++), and in 1991 he brought me in to present them on a Stratus computer. Then the students encouraged me to write what would later become the first edition of this book. Don also introduced me to John White, who agreed to publish it.

My wife, Nancy L. Urbano, continues to encourage my writing, even after seven published books, adapting them for CD and dissertation. She has incredible patience. Without her, I would never have been able to do what I did.

From start to finish, our dog Persephone was my selfless companion. Unfortunately, she participated in most of the project while already in the burial urn. We miss her very much.

Foreword

I wrote the first draft of the book "Using C ++ Effectively" in 1991. When it was time for the second edition in 1997, I significantly updated the material, but, not wanting to embarrass readers familiar with the first edition, I tried to keep the existing structure: 48 of the original The 50 rules have remained essentially unchanged. If you compare the book to a house, then the second edition was like redecorating- wallpapering, painting in other colors and replacement of lighting fixtures.

In the third edition, I decided on much more. (There was a moment when I wanted to rebuild everything, starting from the foundation.) The C ++ language has changed a lot since 1991, and the purpose of this book - to identify everything that is most important and present it in the form of a compact collection of recommendations - no longer met the set of rules formulated for 15 years back. In 1991, it was reasonable to assume that programmers with experience in working with C would switch to C ++. Now, with equal probability, those who previously wrote in Java or C # can be attributed to them. In 1991, inheritance and object-oriented programming were new to most programmers. Now these are well-known concepts, and the areas that people need to clarify more are exceptions, patterns, and generic programming. In 1991, nobody had heard of design patterns. Now, without mentioning them, it is generally difficult to discuss software systems... In 1991, work on a formal C ++ standard was just beginning, now this standard is already 8 years old, and work is underway on the next version.

To accommodate all these changes, I decided to start with blank slate and asked myself, "What advice should I give practicing C ++ programmers in 2005?" The result is a set of rules included in the new edition. This book includes new chapters on pattern programming and resource management. In fact, templates run like a red thread throughout the text, since little in modern C ++ is complete without them. The book also includes material on programming with exceptions, design patterns, and new library tools described in Technical Report 1 (TR1) (discussed in rule 54). It is also recognized that approaches and techniques that work well on single-threaded systems may not be applicable to multi-threaded systems. More than half of the materials in this edition are new topics. However, much of the foundational information from the second edition remains relevant, so I found a way to repeat it in one form or another (see Appendix B for the correspondence between the rules of the second and third editions).

I have tried my best to make this book as useful as possible, but of course I don’t think it is perfect. If it seems to you that some of the above rules cannot be considered universally applicable, that there is a better way to solve the formulated problem, or that the discussion of some technical issues not clear enough, incomplete, may be misleading, please tell me. If you find errors of any kind - technical, grammatical, typographical, - any, - write to me about this. When releasing the next print run, I will gladly mention everyone who draws my attention to some problem.

Despite the fact that in the new edition the number of rules has been increased to 55, of course, it cannot be said that all and all kinds of questions have been considered. But formulating a set of rules that should be followed in almost all applications is more difficult than it might seem at first glance. If you have any suggestions on what else to include, I would love to consider them.


Stafford, Oregon, April 2005

Introduction

It's one thing to study fundamentals language, and quite another - learning to design and implement effective programs. This is especially true of C ++, known for its unusually rich capabilities and expressiveness. Working in C ++, when used correctly, can be fun. A wide variety of projects can be directly expressed and efficiently implemented. A carefully selected and well-implemented set of classes, functions and templates will help make the program simple, intuitive, efficient, and virtually error-free. With the right skills, writing efficient C ++ programs is not difficult at all. However, if used unwisely, C ++ can produce incomprehensible, difficult to maintain, and simply incorrect code.

The purpose of this book is to show you how to use C ++ efficiently. I assume that you are already familiar with C ++ as programming language, and also have some experience with it. I bring to your attention guidelines for the use of this language, following which will make your programs understandable, easy to maintain, portable, extensible, efficient and perform as expected.

The suggested tips can be divided into two categories: overall strategy design and practical use separate language constructions. A design discussion is intended to help you choose between different approaches to solving a given problem in C ++. Should I choose inheritance or templates? Public or private inheritance? Closed inheritance or composition? Member functions or free functions? Pass by value or by reference? It is important to make the right decision from the very beginning, since the consequences of a bad choice may not manifest in any way until it is too late, and it will be difficult, time-consuming and expensive to redo.

Even when you know exactly what you want to do, it can be difficult to achieve the results you want. What type of value should the assignment operator return? When should a destructor be virtual? How does the new operator behave if it cannot find enough memory? It is extremely important to work through these details, because otherwise you will almost certainly run into unexpected and even unexplained program behavior. This book will help you avoid situations like this.

Of course, this book is difficult to name complete guidance in C ++. Rather, it is a collection of 55 tips (or rules) on how to improve your programs and projects. Each paragraph is more or less independent of the others, but most are cross-referenced. The best way to read this book is to start with the rule that interests you the most, and then follow the links to see where they lead you.

This book is also not an introduction to C ++. In Chapter 2, for example, I discuss how to properly implement constructors, destructors, and assignment operators, but I assume that you already know what these functions do and how they are declared. There are many C ++ books on this topic.

Target this books - highlight those aspects of C ++ programming that are often overlooked. Other books describe different parts of the language. It also explains how to combine them with each other to get effective programs. Other editions talk about how to get a program to compile. And this book is about how to avoid problems that the compiler cannot detect.

At the same time, this book is limited to standard C ++. Here, only those language features are used that are described in the official standard. Portability is a key issue for this book, so if you're looking for platform-specific tricks, check out the other editions.

You will not find in this book the "Gospel According to C ++" - the only true path to the ideal C ++ program. Each rule is a recommendation for one aspect or another: how to find a better design, how to avoid typical mistakes how to achieve maximum efficiency, but none of the points are universally applicable. Software design and development is a complex task influenced by constraints hardware, operating system and applications, so the best I can do is present recommendations to improve the quality of programs.

If you systematically follow all the recommendations, then it is unlikely that you will encounter the most common pitfalls that lie in wait for you in C ++, but there are exceptions to any rule. That is why explanations are provided in each rule. They constitute the most important part of the book. Only by understanding what lies at the heart of a particular rule can you decide to what extent it fits your program with its inherent limitations.

The best way to use this book is to understand the secrets of C ++ behavior, understand why it behaves the way it does, and use its behavior to your advantage. Blind application in practice of all the above rules is completely inappropriate, but at the same time, you should not act contrary to these advice without special reasons.

Terminology

There is a small C ++ vocabulary that every programmer should master. The following terms are important enough that it makes sense to make sure we understand them the same way.

Announcement(declaration) tells the compiler the name and type of something, omitting some details. Ads look like this:


extern int x; // object declaration

std :: size_t numDigits (int number); // function declaration

class Widget; // class declaration

template // template declaration

class GraphNode; // (see rule 42 for what "typename" is


Note that I call the integer x "object" even though it is a built-in variable. Some people mean by "objects" only variables of user defined types, but I am not one of them. Also note that the numDigits () function returns type std :: size_t, that is, type size_t from the std namespace. This is the namespace that almost everything from the C ++ Standard Library resides in. However, since the C standard library (more precisely, C89) can also be used in a C ++ program, symbols inherited from C (such as size_t) can exist in global context, inside std, or both, depending on which header files were included with the #include directive. For this book, I am assuming that C ++ header files are included with #include. This is why I am using std :: size_t and not just size_t. When I mention standard library components outside of the code, I usually omit the std reference, assuming you know that things like size_t, vector, and cout are in the std namespace. In the example programs, I always include std, because otherwise the code will not compile.

By the way, size_t is just a synonym defined by the typedef directive for some of the unsigned types used in C ++ for different kinds counters (for example, the number of characters in char * strings, the number of elements in STL containers, etc.). It is also the type accepted by the operator functions in vectors, deques, and strings. We'll follow this convention when we define our own operator functions in rule 3.

Any function declaration specifies its signature, that is, the types of the parameters and the return value. We can say that the signature of a function is its type. So, the signature of the numDigits function is std :: size_t (int), in other words, it is “a function that takes an int and returns std :: size_t”. Official definition"Signatures" in C ++ do not include the return type of the function, but for this book it will be convenient for us to assume that it is still part of the signature.

Definition(definition) tells the compiler the details that are omitted from the declaration. For an object, a definition is where the compiler allocates memory for it. For a function or function template, the definition contains the body of the function. A class definition or class template lists its members:


int x; // object definition

std :: size_t numDigits (int number) // function definition

(// (this function returns the number

std :: size_t digitsSoFar = 1; // decimal places in its parameter)

while ((number / = 10)! = 0) ++ digitsSoFar;

return digitsSoFar;

class Widget (// class definition

template // template definition

class GraphNode (


Initialization(initialization) is the process of initializing an object. For objects of user-defined types, initialization is performed by constructors. Default constructor(default constructor) is a constructor that can be called with no arguments. Such a constructor either has no parameters at all, or has a default value for each parameter:


A (); // default constructor

explicit B (int x = 0; bool b = true); // default constructor,

// the keyword "explicit"

explicit C (int x); // this is not a constructor by

// default


The constructors of classes B and C are declared with the explicit keyword. This prevents them from being used for implicit conversions, although it does not prevent them from being used if the conversion is specified explicitly:


void doSomething (B bObject); // function takes an object of type B

B bObj1; // object of type B

doSomething (bObj1); // ok, B is passed to doSomething

B bObj (28); // ok, creates B from integer 28

// (parameter bool is true by default)

doSomething (28); // error! doSomething accepts B,

// not int, and there is no implicit

// conversions from int to B

doSomething (B (28)); // ok, constructor is used

// B for explicit conversion (casting)

// int in B (see rule 27 for information

// about type casting)


Constructors declared explicit are generally preferred because they prevent compilers from performing implicit (often unwanted) type conversions. Unless there is a good reason for using constructors in implicit conversions, I always declare them explicit. I advise you to adhere to the same principle.

Note that in the preceding example, the cast is highlighted. I will continue to use this emphasis to emphasize the importance of the material presented. (I also highlight the chapter numbers, but that's only because I think it looks cute.)

Copy constructor(copy constructor) is used to initialize an object with the value of another object of the same type, and copy assignment operator(copy assignment operator) is used to copy the value of one object to another - of the same type:


Widget (); // default constructor

Widget (const Widget & rhs); // copy constructor

Widget & operator = (const Widget & rhs); // copy assignment operator

Widget w1; // call the default constructor

Widget w2 (w1); // call the copy constructor

w1 = w2; // call the assignment operator

// copy


Be careful when you see an assignment-like construct, because the "=" syntax can also be used to call the copy constructor:


Widget w3 = w2; // call the copy constructor!


Fortunately, a copy constructor is easy to distinguish from an assignment. If a new object is defined (like w3 in the last clause), then the constructor must be called, it cannot be an assignment. If no new object is created (as in "w1 = w2"), then the constructor is not applied and this is an assignment.

The copy constructor is especially important because it defines how an object is passed by value. For example, consider the following snippet:


bool hasAcceptableQuality (Widget w);

if (hasAcceptableQuality (aWidget)) ...


The w parameter is passed by value to the hasAcceptableQuality function, so in the above example call aWidget is copied to w. Copying is done by the copy constructor from the Widget class. Generally passing by value means a call to the copy constructor. (But, strictly speaking, passing custom types by value is bad idea... Usually the best option is to pass by reference to a constant; see Item 20 for details.)

STL- the Standard Template Library is the part of the standard library dealing with containers (i.e. vector, list, set, map, etc.), iterators (i.e. vector :: iterator, set :: iterator, etc.) etc.), algorithms (i.e. for_each, find, sort, etc.) and all related functionality. It is very widely used function objects(function objects), that is, objects that behave like functions. Such objects are represented by classes in which the call operator operator () is overloaded. If you are not familiar with the STL, you will need, in addition to this book, some decent manual on this topic, because the STL library is so convenient that it would be unforgivable not to take advantage of its benefits. One has only to start working with her, and you yourself will feel it.

For programmers who have come to C ++ from languages ​​like Java or C #, the concept of undefined behavior. For various reasons, the behavior of some constructs in C ++ is really undefined: you cannot predict with certainty what will happen at runtime. Here are two examples of this kind:


int * p = 0; // p is a null pointer

char name = “Daria” // name is an array of length 6 (don't forget about

// trailing null!)

char c = name; // specifying the wrong array index

// spawns undefined behavior


To emphasize that the results of undefined behavior cannot be predicted and that they can be quite unpleasant, experienced C ++ programmers often say that programs with undefined behavior can erase the contents of the hard disk. It's true: such a program maybe erase your HDD, but it may not. It is more likely to behave differently, sometimes ok, sometimes crashing, and sometimes just giving incorrect results. Wise C ++ programmers adhere to the rule of avoiding undefined behavior. Throughout this book, I show you how to do this in many places.

Another term that may confuse programmers who came from other languages ​​is interface. In Java and. NET-compatible languages, interfaces are part of the language, but C ++ doesn't have anything like that, although Rule 31 deals with some approximation. When I use the term "interface", I usually mean function signatures, accessible class members ("public interface", "protected interface", " closed interface") Or expressions allowed as type parameters for templates (see Item 41). That is, by interface I mean a general design concept.

Concept customer Is something or someone that uses code you write (usually through interfaces). So, for example, the clients of a function are its users: the parts of the code that call the function (or take its address), as well as the people who write and maintain such code. Clients of a class or template are parts of a program that use that class or template, as well as programmers who write or maintain those parts. When it comes to clients, I usually mean programmers because they can be misled or frustrated by poorly designed interfaces. The code they write doesn't have such emotions.

You may not be used to thinking about clients, but I will try to convince you of the need to make their life as easy as possible. After all, you yourself are a client of software that someone else developed. After all, you would like its authors to make your work easier? In addition, sooner or later you will find yourself in a position where you yourself become a client of your own code (that is, you will use the code you write), and then you will appreciate that when designing interfaces you need to keep the interests of clients in mind.

Throughout this book, I often focus on the difference between functions and function templates, and between classes and class templates. This is not accidental, because what is true for one is often true for another. In situations where this is not the case, I make a distinction between classes, functions, and templates from which classes and functions are derived.

Naming convention

I've tried to choose meaningful names for objects, classes, functions, templates, etc., but the semantics of some of the names I came up with may not be clear to you. For example, I often use the names lhs and rhs for parameters. This refers to the "left-hand side" and "right-hand side", respectively. These names are commonly used in functions that implement binary operators, that is, operator == and operator *. For example, if a and b are objects that represent rational numbers, and if the objects of the Rational class can be multiplied by the non-member function operator * () (a similar case is described in rule 24), then the expression



is equivalent to calling a function:


operator * (a, b);


In rule 24, I declare operator * like this:


const Rational operator * (const Rational & lhs, const Rational & rhs);


As you can see, the left operand - a - inside the function is called lhs, and the right one - b - rhs.

For member functions, the argument on the left side of the statement is represented by the this pointer, and the only remaining parameter I sometimes call rhs. You may have noticed this in the declarations of some of the Widget member functions in the examples above. "Widget" doesn't mean anything. It's just a name that I sometimes use to somehow name an example class. It has nothing to do with the controls (widgets) used in graphical interfaces(GUI).

I often name pointers following the convention that a pointer to an object of type T is called pt ("pointer to T"). Here are some examples:


Widget * pw; // pw = pointer to Widget

Airplane * pa; // pa = pointer to Airplane

class GameCharacter;

GameCharacter * pgc; // pgc = pointer to GameCharacter


A similar convention applies to links: rw can be a Widget link, and ra can be an Airplane link.

Sometimes I use the name mf to name the member function.

Multithreading

In the C ++ language itself, there is no idea about threads, and indeed about any mechanisms of parallel execution. The same is true for the C ++ standard library. In other words, from the point of view of C ++, multithreaded programs do not exist.

However, they are. While I'll be focusing primarily on standard, portable C ++ throughout this book, it's impossible to ignore the fact that thread safety is a requirement faced by many programmers. In recognition of this conflict between standard C ++ and reality, I will note where the constructs in question can cause problems when working in a multithreaded environment. Don't think that this book will teach you about multithreading C ++ programming. Not at all. I have looked at mostly single-threaded applications, but I have not ignored the existence of multi-threading and have tried to note when programmers writing multi-threaded programs should follow my advice with caution.

If you are not familiar with the concept of multithreading and are not interested in this topic, then you can ignore the notes related to it. Otherwise, keep in mind that my comments are nothing more than a humble hint of what you need to know if you are going to use C ++ to write multithreaded programs.

TR1 and Boost libraries

You will see references to the TR1 and Boost libraries throughout this book. Each of them has a separate rule (54 - TR1 and 55 - Boost), but, unfortunately, they are at the very end of the book. You can read them right now if you want, but if you prefer to read the book in order rather than from the end, then the following notes will help you understand what is at stake:

TR1 ("Technical Report 1") is a specification of new functionality added in standard library C ++. It is framed with new class templates and functions designed to implement hash tables, smart pointers with reference counting, regular expressions, and more. All TR1 components are in the tr1 namespace, which is nested under the std namespace.

Boost is an organization and website (http://boost.org) that offers portable, well-tested, open source C ++ libraries. source code... Much of TR1 builds on the work done by Boost, and until compiler vendors include TR1 in C ++ distributions, the Boost Web site will remain the main source of TR1 implementations for developers. Boost provides more than what's included in TR1, but it's good to know about it anyway.

Get used to C ++

Regardless of programming experience, getting comfortable with C ++ will take some time. It is a powerful language with very wide range opportunities, but to use them effectively, you need to slightly change your way of thinking. The book is designed to help you with this, but some questions are more important, some less, and this chapter is devoted to the most important things.

Rule 1: Treat C ++ as a Conglomerate of Languages

In the beginning, C ++ was just a C language with some object-oriented features added. Even the original C ++ name ("C with Classes") reflects this relationship.

As the language matured and grew and developed, it included programming ideas and strategies that went beyond C with classes. The exceptions required a different approach to structuring functions (see rule 29). Templates have changed the way we design programs (see Item 41), and the STL has introduced an approach to extensibility that no one else could have imagined.

Today C ++ is a language programming with multiple paradigms, supporting procedural, object-oriented, functional, generic and metaprogramming. This power and flexibility makes C ++ an incomparable tool, but it can be confusing. Any recommendation for “ correct application»There are exceptions. How do you find meaning in such a language?

It is best to think of C ++ not as a single language, but as a conglomeration of interconnected languages. Within a separate sublanguage, the rules are quite simple, understandable and easy to remember. However, when you move from one sublanguage to another, the rules may change. To see the point in C ++, you must recognize its major sublanguages. Fortunately, there are only four of them:

C. In its depths, C ++ is still based on C. Blocks, statements, preprocessor, built-in data types, arrays, pointers, etc. all come from C. In many cases, C ++ provides more advanced mechanisms for solving certain problems, than C (for an example, see rule 2 - an alternative to the preprocessor and 13 - using objects to manage resources), but when you start working with the part of C ++ that has analogues in C, you will realize that the rules of effective programming reflect the more limited nature of the language C: no templates, no exceptions, no overload, etc.

Object Oriented C ++. This part of C ++ represents what "C with classes" was, including constructors and destructors, encapsulation, inheritance, polymorphism, virtual functions(dynamic linking) etc. This is the part of C ++ to which in the most the classic rules of object-oriented design apply.

C ++ with templates. This part of C ++ is called generic programming, and most programmers know little about it. Templates now permeate C ++ from bottom to top, and it is a sign of good programming practice to include constructs unthinkable without templates (for example, see rule 46 on type conversions when calling templated functions). In fact, templates, thanks to their power, have spawned an entirely new programming paradigm: template metaprogramming(template metaprogramming - TMP). Rule 48 provides an overview of TMP, but unless you are a die-hard template fanatic, you have no reason to overthink it. TMP is not one of the most common C ++ programming practices.

STL. STL is, of course, a templating library, but very specialized. The conventions it makes about containers, iterators, algorithms, and functional objects work together beautifully, but templates and libraries can be built differently. When working with the STL, you must follow its conventions.

Keep these four sublanguages ​​in mind, and don't be surprised if you find yourself in a situation where programming efficiency requires you to change your strategy when switching from one sublanguage to another. For example, for built-in types (C style) passing parameters by value in general case is more efficient than passing by reference, but if you are programming in an object-oriented style, then passing by reference to a constant usually becomes more efficient due to the presence of user-defined constructors and destructors. This is especially true for the "C ++ with Templates" sublanguage, because there you usually don't even know in advance the type of objects you are dealing with. But now you switched to using STL, and again the old C rule about passing by value becomes relevant, because iterators and function objects are modeled through C pointers. (For details on choosing a method for passing parameters, see rule 20.)

Thus, C ++ is not a homogeneous language with a single set of rules. It is a conglomerate of sublanguages, each with its own conventions. If you keep these sublanguages ​​in mind, you will find that C ++ is much easier to understand.

Things to Remember

The rules for effective programming change depending on the part of C ++ you are using.

Rule 2: Prefer const, enum and inline over #define

It would be better to call this rule "Compiler is preferable to preprocessor", since #define is often not referred to as C ++ language at all. This is the problem. Let's look at a simple example; try writing something like:


#define ASPECT_RATIO 1.653


The symbolic name ASPECT_RATIO may remain unknown to the compiler or be removed by the preprocessor before the code is processed by the compiler. If this happens, the name ASPECT_RATIO will not be included in the symbol table. Therefore, during compilation, you will receive an error (the message will mention the value 1.653, not ASPECT_RATIO). This will cause confusion. If the ASPECT_RATIO name was defined in a header file that you didn’t write, then you will not even know where the value of 1.653 came from, and you will spend a lot of time looking for an answer. The same problem can occur when debugging as the name you choose will not be in the symbol table.

The solution is to replace the macro with a constant:


const double AspectRatio = 1.653; // names written in big letters,

// usually used for macros,

// so we decided to change it


As a language constant, AspectRatio is visible to the compiler and is naturally placed in the symbol table. In addition, using a floating point constant (as in this example) generates more compact code than using #define. The fact is that the preprocessor, blindly substituting the value 1.653 instead of the ASPECT_RATIO macro, creates many copies of 1.653 in the object code, while using a constant will never generate more than one copy of this value.

When replacing # define constants two things to remember special cases... The first concerns constant pointers. Since constant definitions are usually placed in header files (where they are accessed by many different source files), it is important that pointer was declared with the const keyword, in addition to the const declaration of what it points to. For example, to declare a constant string of type char * in the header file, the word const should be written twice:


const char * const authorName = “Scott Meyers”;


For more information on the nature and uses of the word const, especially in conjunction with pointers, see Rule 3. But already now it is worth recalling that objects of type string are usually preferable to their ancestors - strings of type char *, so it is better to define authorName like this:


const std :: string authorName (“Scott Meyers”);


The second note concerns the constants declared within the class. To limit the scope of a constant to a class, you must make it a member of the class, and to ensure that only one copy of the constant exists, you must make it static member of:


class GamePlayer (

static const int NumTurns = 5; // constant declaration

int scores; // using a constant


What you see above is announcement NumTurns, not its definition. Usually C ++ requires you to provide a definition for everything you use, but constants declared in a class that are static and of built-in type (i.e., integers, char, boolean) are an exception to the rule. As long as you don't try to get the address of such a constant, you can declare and use it without providing a definition. If you need to get an address, or if your compiler insists on a definition, you can write something like this:


const int GamePlayer :: NumTurns; // definition of NumTurns; see below,

// why the value is not specified


Place this code in an implementation file, not in a header file. Since the initial value of the class constant is represented where it is declared (that is, NumTurns is initialized to 5 when declared), there is no need to specify an initial value at the definition point.

Note, by the way, that it is not possible to declare a constant in a class using #define, because #define is not scoped. Once a macro is defined, it remains in effect for the rest of the compiled code (unless #undef is found somewhere below). This means that the #define directive is inapplicable not only for declaring constants in a class, but generally cannot be used to provide any kind of encapsulation, that is, it is impossible to give meaning to the expression "private #define". At the same time, constant member data can be encapsulated, for example NumTurns.

Older compilers may not support the syntax shown above because earlier versions of the language were not allowed to set the values ​​of static class members during declaration. Moreover, initialization in the class was allowed only for integer types and for constants. If the above syntax does not work, then the initial value should be specified in the definition:


class CostEstimate (

static const double FudgeFactor; // declaration of a static constant

... // class - placed in the header file

const double // definition of a static constant

CostEstimate :: FudgeFactor = 1.35; // class - placed in the implementation file


Usually nothing else is required. The only exception is thrown when a constant is needed to compile a class. For example, when declaring an array GamePlayer :: scores, the compiler needs to know the size of the array. To work with a compiler that mistakenly prohibits initializing static integer constants within a class, you can use a technique known as the enumeration trick. It is based on the fact that enumerated variables can be used where int values ​​are expected, so the GamePlayer can be defined like this:


class GamePlayer (

enum (NumTurns = 5); // "trick with enumeration" - makes from

// NumTurns character with value 5

int scores; // fine


This technique is worth knowing for several reasons. First, the enumeration trick's behavior is in some respects more like #define than constant, and sometimes that's just what you want. For example, you can get the address of a constant, but you cannot get the address of an enumeration, just as you cannot get the address #define. If you want to prevent getting an address or reference to some integer constant, then using an enum is a good way to impose such a restriction. (See rule 18 for more information on supporting design constraints with coding techniques.) Plus, while good compilers don't allocate memory for constant integer objects (unless you create a pointer or object reference), less sophisticated compilers can do this, and you probably don't need it. Like #define, enums will never cause this kind of unwanted memory allocation.

The second reason to know about the enumeration trick is purely pragmatic. It is used in so many programs, so you need to be able to recognize this trick when you encounter it. Generally speaking, this technique is a fundamental technique used in template metaprogramming (see Item 48).

Let's go back to the preprocessor. Another common misuse of the #define directive is creating macros that look like functions but are not burdened with the overhead of function calls. Below is a macro that calls some function f with an argument equal to the maximum of two values:


// call f, passing the maximum of a and b to it

#define CALL_WITH_MAX (a, b) f ((a)> (b)? (a): (b))


There are so many flaws in this line that it's not entirely clear where to start.

Whenever you write a macro like this, you must remember that all arguments must be enclosed in parentheses. Otherwise, you run the risk of running into a problem when someone calls it with an expression as an argument. But even if you get it right, see what strange things can happen:


int a = 5, b = 0;

CALL_WITH_MAX (++ a, b); // a is incremented twice

CALL_WITH_MAX (++ a, b + 10); // a is incremented once


What happens inside max depends on what it is being compared to!

Fortunately, you don't have to put up with behavior that goes against your usual logic. There is a method to achieve the same efficiency as using the preprocessor. But it provides both predictable behavior and control of the types of arguments (which is typical for ordinary functions). This is achieved by using the inline function template (see rule 30):


inline void callWithMax (const T & a, const T & b) // Since We Don't Know

(// what is T, then we pass

) // see paragraph 20


This template generates a whole family of functions, each of which takes two arguments of the same type and calls f with the largest of them. There is no need to put parentheses around the parameters inside the function body, no need to worry about evaluating parameters over and over, and so on. Moreover, since callWithMax is a real function, it is subject to scoping and access control rules. For example, you can talk about a built-in function that is a private member of a class. It is impossible to describe something like this using a macro.

The presence of const, enum and inline drastically reduces the need for a preprocessor (especially for #define), but does not completely eliminate it. The #include directive remains essential, and # ifdef / # ifndef continues to play an important role in controlling compilation. It's not time to ditch the preprocessor just yet, but it's definitely worth considering how to get rid of it in the future.

Things to Remember

For simple constants, the #define directive should be preferred over constant objects and enumerations.

Instead of macros that mimic functions, defined via #define, it is better to use built-in functions.

Rule 3: Use const wherever possible

The cool thing about the const modifier is that it imposes a certain semantic constraint: a given object must not be modified, and the compiler will enforce this constraint. const allows you to tell the compiler and programmers that a certain value should remain unchanged. In all such cases, you must state this explicitly, calling on the compiler to help you and thereby ensuring that the constraint is not violated.


This syntax is not as scary as it might seem. If the word const appears to the left of the asterisk, the constant is what the pointer points to; if on the right, then the pointer itself is constant. Finally, if the word const appears on both sides, then both are constant.

Notes (edit)

There is a Russian translation: Sutter Coat of arms. Solving complex problems in C ++. Publishing House "Williams", 2002 (Editor's note).

There is a Russian translation: Design Patterns. SPb .: Peter (Editor's note).

End of free trial snippet.

  • Pages:
    , ,
  • Reviews of the third edition
    Effective use of C ++

    Scott Meyers book Using C ++ Effectively, Third Edition- is the concentration of programming experience - the experience that without it would have gotten you dearly. This book is an excellent resource that I recommend to anyone writing C ++ professionally.

    Peter Dulimov, ME, Engineer, Evaluation and Research Unit, NAVSYSCOM, Australia

    Third Edition remains the best book on how to put all the pieces of C ++ together to create efficient and consistent programs. If you are applying to be a C ++ programmer, then you should read it.

    Eric Nagler, Consultant, Trainer and Author of Learning C ++

    The first edition of this book was one of a small (very small) number of books that helped me to significantly improve my level as a professional software developer. Like other books in this series, it turned out to be practical and easy to read, but it also contained many important tips. "Effective use C ++ ", third edition, continues this tradition. C ++ is a very powerful programming language. If C gives you a rope to climb to the top of a mountain, then C ++ is a whole store where all kinds of people are ready to help you tie the knots on that rope. Mastering the material in this book will definitely increase your ability to use C ++ effectively without dying of stress.

    Jack W. Reeves, CEO, Bleading Edge Software Technologies

    Every new developer who joins my team is immediately assigned the task of reading this book.

    Michael Lancetta, Lead Software Engineer

    I read the first edition of Effectively Using C ++ about 9 years ago, and this book immediately became one of my favorite C ++ books. In my opinion, the third edition of Effectively Using C ++ remains a must-read for anyone who wants to program effectively in C ++. We will live in a better world if C ++ programmers read this book before writing the first line of professional code.

    Danny Rabbani, software engineer

    The first edition of Scott Meyers' Effective Use of C ++ came to me when I was an average programmer and tried hard to do the best job I could. And that was salvation! I have found that Meyers' advice is practically helpful and effective, that it will 100% deliver what it promises. The third edition helps in the practical use of C ++ when working on modern serious software projects, providing information about the latest features and capabilities of the language. I discovered with pleasure that I could find a lot of new and interesting things for myself in the third edition of the book, which, as it seemed to me, I know very well.

    Michael Topek, Technical Program Manager

    This authoritative guide from Scott Meyers, a C ++ guru, is intended for anyone who wants to use C ++ safely and efficiently, or who is migrating to C ++ from any other object-oriented language. This book contains valuable information presented in a clear, concise, entertaining and insightful style.

    Siddhartha Karan Singh, Software Developer

    Acknowledgments

    The book "Using C ++ Effectively" has been around for 15 years, and I started learning C ++ about 5 years before I wrote it. Thus, work on this project has been going on for about 20 years. During this time, I received wishes, comments, corrections, and sometimes overwhelming observations from hundreds (thousands?) Of people. Each of them contributed to the development of "Effective Use of C ++". I am grateful to all of them.

    I have long given up trying to remember where and what I learned myself, but I cannot but mention one source, since I use it all the time. These are Usenet newsgroups, especially comp.lang.c ++. Moderated and comp.std.c ++. Many of the rules in this book (perhaps most) are the result of thinking about the technical ideas discussed in these groups.

    Steve Dewhurst assisted me in selecting new material for the third edition of the book. Rule 11 takes the idea of ​​copy-and-swap implementation of operator = from Herb Sutter's notes, Problem 13 of his book Exceptional C ++ (Addison-Wesley, 2000). The idea of ​​grabbing a resource as initialization (rule 13) comes from The C ++ Programming Language (Addison-Wesley, 2002) by Bjarne Stroustrup. The idea behind Rule 17 is taken from the "Best practices" section of the Boost shared_ptr site (http://boost.org/libs/ smart_ptr / shared_ptr.htm # BestPractices) and refined based on the material in problem 21 in the book Herb Sutter, "More exceptional C ++" (Addison-Wesley, 2002). Rule 29 was inspired by Herb Sutter's extensive exploration of this topic in Exceptional C ++ Problems 8-19, More exceptional C ++ Problems 17-23 and Exceptional C ++ Problems 11-13. Style ”(Addison-Wesley, 2005). David Abrahams helped me better understand the three principles of making sure exceptions are safe. The non-virtual interface (NVI) idiom in Rule 35 is taken from Sutter's column "Virtuality" in the September 2001 C / C ++ Users Journal. The Template Method and Strategy design patterns mentioned in the same rule are taken from Design Patterns (Addison-Wesley, 1995) by Erich Gamma, Richard Helm, Ralph Johnson ( Ralf Johnson and John Vlissides. The idea for the NVI idiom in rule 37 came from Hendrik Schober. David Smallberg's contribution to the set implementation described in Item 38. The observation in Item 39 that optimization of an empty base class is fundamentally impossible with multiple inheritance is from David Vandevoorde and Nikolai M. Jossutis (Nickolai M. Josuttis) "Templates C ++" (Addison-Wesley, 2003). My initial idea of ​​what the typename keyword is in Rule 42 is based on the C ++ and C FAQ ( http://www.comeaucomputing.com/techtalk/#typename), supported by Greg Comeau, and Leor Zolman helped me realize that this view is wrong (my fault, not Greg's). The theme for rule 46 originated from Dan Saks' speech "How to Make New Friends." The idea at the end of rule 52 that if you declare one version of new, you must declare all the others, is outlined in problem 22 of Herb Sutter's Exceptional C ++. My understanding of the Boost review process (summarized in rule 55) was refined by David Abrahams.

    All of the above concerns where and from whom I learned something, regardless of who first published the material on the relevant topic.

    My notes also say that I used information from Steve Clamage, Antoine Trux, Timothy Knox and Mike Kaelbling, although unfortunately it is not specified where And How.

    First edition drafts reviewed by Tom Cargill, Glenn Caroll, Tony Davis, Brian Kernigan, Jak Kirman, Doug Lea, Moises Lejter), Eugene Santos Jr. (Eugene Santos, Jr), John Shewchuk, John Stasko, Bjarne Stroustrup, Barbara Tilly and Nancy L. Urbano. In addition, suggestions for improvements that have been incorporated into later reissues were expressed by Nancy L. Urbano, Chris Treichel, David Corbin, Paul Gibson, Steve Vinoski, Tom Tom Cargill, Neil Rhodes, David Bern, Russ Williams, Robert Brazile, Doug Morgan, Uwe Steinmuller, Mark Somer (Mark Somer), Doug Moore, David Smallberg, Seith Meltzer, Oleg Steinbuk, David Papurt, Tony Hansen, Peter McCluskey ), Stefan Kuhlins, David Braunegg, Paul Chisholm, Adam Zell, Clovis Tondo, Mike Koelbling, Natraj Kini, Lars Numan, Greg Lutz, Tim Johnson, John Lakos, Roger Scott, Scott Frohman, Alan R ooks, Robert Poor, Eric Nagler, Anton Trucks, Cade Roux, Chandrika Gokul, Randy Mangoba and Glenn Teitelbaum.

    Second Edition drafts reviewed by: Derek Bosch, Tim Johnson, Brian Kernighan, Junichi Kimura, Scott Lewandowski, Laura Michaels, David Smallberg, Clovis Tonado, Chris Van Wyk and Oleg Zabluda. Later runs have benefited from comments from Daniel Steinberg, Arunprasad Marathe, Doug Stapp, Robert Hall, Cheryl Ferguson, Gary Bartlett, Michael Bartl Tam Michael Tamm, Kendall Beaman, Eric Nagler, Max Hailperin, Joe Gottman, Richard Weeks, Valentin Bonnard, Jun He, Tim King, Don Mailer, Ted Hill, Marc Harrison, Michael Rubinstein, Marc Rodgers, David Goh, Brenton Brenton Cooper, Andy Thomas-Cramer, Anton Trucks, John Walt, Brian Sharon, Liam Fitzpatric, Bernd Mohr, Harry Yee (Gary Yee), John O "Hanley, Brady Paterson, Christopher Peterson (Christ opher Peterson, Feliks Kluzniak, Isi Dunetz, Christopher Creutzi, Ian Cooper, Carl Harris, Marc Stickel, Clay Budin ), Panayotis Matsinopulos, David Smallberg, Herb Sutter, Pajo Misljencevic, Giulio Agostini, Fredrik Blomqvist (Fredrik Blimqvist), Jensender Jensender Witold Kuzminski, Kazunobu Kuriyama, Michael Christensen, Jorge Yanez Teruel, Mark Davis, Marty Rabinowitz, Ares Lagae (Ares Lagae) and Alexander Medvedev.

    Early partial drafts of this edition were reviewed by: Brian Kernighan, Angelica Lunger, Jesse Lachley, Roger P. Pedersen, Chris Van Wyck, Nicholas Stroustrup and Hendrick Schober. The full draft was reviewed by: Leor Zolman, Mike Tsao, Eric Nagler, Zhenet Gutnik, David Abrahams, Gerhard Kreuser, Drosos Kouronis, Brian Kernigan, Andrew Crims, Balog Pal, Emily Jagdhar, Eugene Kalenkovich, Mike Rose, Benjko Carrarara, , Jack Reeves, Steve Shirippa, Martin Fallenstedt, Timothy Knox, Yoon Bai, Michael Lancetta, Philip Janert, Judo Bartholucci, Michael Topic, Jeff Scherpeltz, Chris Naurot, Nishant Mittal, Jeff Sommers, Hrendon Morungoff Lee, Jim Meehan, Alan Geller, Siddhartha Singh, Sam Lee, Sasan Dashinejad, Alex Martin, Steve Cai, Thomas Fruchterman, Corey Hicks, David Smallberg, Gunawardan Kakulapati, Danny Rabbani, Jake Cohen, Hendrik Schuber, Paco Wiziana, Glenn Jeffrey D. Oldham, Nicholas Stroustrup, Matthew Wilson, Andrei Alexandrescu, Tim Johnson, Leon Matthews, Peter Dulimov, and Kevlin Henney. Some individual paragraphs were also drafted by Herb Sutter and Attila F. Feher.

    Reviewing a raw (and possibly incomplete) manuscript is difficult work, and having tight deadlines only makes it even more difficult. I am grateful to everyone who has expressed a desire to help me with this.

    Viewing the manuscript is all the more difficult if you have no idea about the material, but should not miss none inaccuracies that could have crept into the text. It is amazing that there are people willing to edit texts. Christa Meadowbrook was the editor of this book and was able to identify many mistakes that everyone else has missed.

    Leor Zolman checked all the code examples on various compilers during the manuscript review, and then did it again after I made the changes. If any mistakes remain, I am responsible for them, not Leor.

    Karl Wigers and especially Tim Johnson wrote a short but useful cover text.

    John Waite, editor of the first two editions of this book, inadvertently agreed to work in this capacity again. His assistant, Denise Mikelsen, invariably responded with a pleasant smile to my frequent and annoying remarks (at least I think so, although I have never personally met her). Julia Nahil "pulled out a short straw", she had to be in charge of the production of this book. For six weeks, she sat at night to keep up with her schedule without losing her composure. John Fuller (her boss) and Marty Rabinovich (her boss) were also directly involved in the preparation of the publication. Vanessa Moore's official duties were to layout the book in FrameMaker and create the PDF text, but she volunteered to add Appendix B and format it for printing on the inside cover. Solveig Hugland helped with the index. Sandra Schreueder and Chuti Praserzit were in charge of the cover design. It was Chuchi who had to redo the cover every time I said, "How about putting this photo in, but with a different color strip?" Chanda Lehry-Cooty was completely exhausted marketing the book.

    For several months while I was working on the manuscript, the TV series Buffy the Vampire Slayer helped me relieve stress at the end of the day. It took a lot of effort to banish Buffy's talk from the pages of this book.

    Katie Reed taught me programming in 1971, and I'm glad we remain friends to this day. Donald French hired Moses Lejter and me to develop C ++ tutorials in 1989 (which made me really learn C ++), and in 1991 he brought me in to present them on a Stratus computer. Then the students encouraged me to write what would later become the first edition of this book. Don also introduced me to John White, who agreed to publish it.

    My wife, Nancy L. Urbano, continues to encourage my writing, even after seven published books, adapting them for CD and dissertation. She has incredible patience. Without her, I would never have been able to do what I did.

    From start to finish, our dog Persephone was my selfless companion. Unfortunately, she participated in most of the project while already in the burial urn. We miss her very much.

    Top related articles