From 385199cc90c982a44c99261485bd1a411bf551c9 Mon Sep 17 00:00:00 2001 From: Florian Thake <49362452+Florian-Thake@users.noreply.github.com> Date: Thu, 25 Apr 2019 20:21:50 +0200 Subject: [PATCH] Added bad and good example to NR.5 in CppCoreGuidelines.md (#1401) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added bad and goof example to NR.5 in CppCoreGuidelines.md Added bad and good example to NR.5 Don’t: Don’t do substantive work in a constructor; instead use two-phase initialization. I think it could be suitable. * adjusted coding style * removed extra space * removed one more whitespace * removed spaces before note to make it a blank line * made Cleanup method from bad example return void * some changes after review comments - removed try catch - removed defaulted dtor - changed int to size_t, removed check for even. - Expects() for invariant check - typo * spell check adjustment * moved comment up for met the line length * changed variablename in good example ... they were named same after removed the try catch scope * changed afer comments - changed check_size() function to a static member function - fixed comment mentioning the default contract violation behavior. --- CppCoreGuidelines.md | 83 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 3930c15..06cce5b 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -20030,9 +20030,88 @@ Following this rule leads to weaker invariants, more complicated code (having to deal with semi-constructed objects), and errors (when we didn't deal correctly with semi-constructed objects consistently). -##### Example +##### Example, bad - ??? + class Picture + { + int mx; + int my; + char * data; + public: + Picture(int x, int y) + { + mx = x, + my = y; + data = nullptr; + } + + ~Picture() + { + Cleanup(); + } + + bool Init() + { + // invariant checks + if (mx <= 0 || my <= 0) { + return false; + } + if (data) { + return false; + } + data = (char*) malloc(x*y*sizeof(int)); + return data != nullptr; + } + + void Cleanup() + { + if (data) free(data); + data = nullptr; + } + }; + + Picture picture(100, 0); // not ready-to-use picture here + // this will fail.. + if (!picture.Init()) { + puts("Error, invalid picture"); + } + // now have a invalid picture object instance. + +##### Example, good + + class Picture + { + size_t mx; + size_t my; + vector data; + + static size_t check_size(size_t s) + { + // invariant check + Expects(s > 0); + return s; + } + + public: + // even more better would be a class for a 2D Size as one single parameter + Picture(size_t x, size_t y) + : mx(check_size(x)) + , my(check_size(y)) + // now we know x and y have a valid size + , data(mx * my * sizeof(int)) // will throw std::bad_alloc on error + { + // picture is ready-to-use + } + // compiler generated dtor does the job. (also see C.21) + }; + + Picture picture1(100, 100); + // picture is ready-to-use here... + + // not a valid size for y, + // default contract violation behavior will call std::terminate then + Picture picture2(100, 0); + // not reach here... ##### Alternative