CPP Quirks

You might also like

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 14

A Quick Warm-Up

Q: Is there a problem with the following code?


y memset(&ClassInstance, 0, sizeof(Class));

A: Yes if Class has a v-table.


y The pointer to It would be NULLed. y When you try to call a virtual function youd

get NULL dereference.

Solution: Implement a Clear()\ Reset()\ Zero() method

Memory Leaks and RAII

Q: Can there be a leak in the following code?


y std::vector<Class*> vec; y vec.push_back(new Class);

A: Yes If there is an exception at the push_back() method. Solution: Use a smart-pointer:


y std::vector< Boost::shared_ptr<Class> > vec; y Boost::shared_ptr<Class> class_ptr(new Class); y vec.push_back(class_ptr);

But Boxees Code Doesnt Throw Exceptions?!

Its very hard to write C++ code with no exceptions at all:


y Calling new throws if out-of-memory. y Several STL methods throw (like vector::at()) y SE_Translator usage under the Windows

platform.
-> access violation would cause an exception to be thrown.

Memory Leaks and Ctors

Q: Can there be a leak in the following code?


y Class::Class() { y m_r = FunctionThatAllocateResource(); y MethodThatThrowsException(); // Non-

virtual! }

A: Yes if an exception is thrown inside the ctor, the dtor is never called. Solution: The same as before make m_r a RAII class.

Dtors and Exceptions


Q: Whats wrong with this code?


y ~Class() {MethodThatThrowsException();}

A: Imagine the following code:


y { Class c; y throw std::exception(); {

Solution: Always use a try{} and catch(){} block at a dtor.

The tale of 2 enums

Q: Can there be a problem with this code?


y enum FMT_TYPE; y enum ISMD_FMT_TYPE; y Switch(audioFormat) { Case AUDIO_FMT_PCM:
y ismdAudioFormat = ISMD_ AUDIO_FMT_PCM;

Case AUDIO_FMT_AC3:
y ismdAudioFormat = ISMD_ AUDIO_FMT_AC3;

Case AUDIO_FMT_TRUEHD:
y ismdAudioFormat = ISMD_ AUDIO_FMT_TRUEHD;

The tale of 2 enums: X-Macros (I)

A: Yes there could be a copy-paste mistake.


y i.e.: Mismatch between the FMT_TYPE and

the appropriate ISMD_FMT_TYPE.

Solution: Use X-Macros: In File AudioFmt.x.h:

y y y y

X(AUDIO_FMT_PCM); X(AUDIO_FMT_AC3); X(AUDIO_FMT_TRUHD);

The tale of 2 enums: X-Macros (II)

In the CPP file:


y #define X(var) var, y enum FMT_TYPE = { #include AudioFmt.x.h }; y #undef X y #define X(var) ISMD ## var, y ISMD_FMT_TYPE aISMDFormat = { #include AudioFmt.x.h }; y y ismdAudioFormat = aISMDFormat

[audioFormat];

Exception Guarantees (I)


Basic Guarantee No leaks, valid but undetermined state. Strong guarantee Valid and known state (Like a DB ). Nothrow guarantee Always succeed and never throws.

y As already mentioned very hard to achieve.

Q: How to get a strong guarantee? Solution: Use the pImpl idiom, followed by the copy-and-swap strategy.

Exception Guarantees (II)


PImpl Idiom (compilation independency): class DB_Class {

y private: y std::tr1::shared_ptr<PMImpl> pImpl; };

Copy-and-Swap (strong guarantee): void DB_Class::ChangeState() {

y using std::swap; y std::tr1::shared_ptr<PMImpl> pNew(new

PMImpl(*pImpl)); // Copy the data. y pNew->ReallyChangeState(); // modify the copy. y swap(pImpl, pNew); }

Some More Good Practices

Use unsigned instead of int type for loops and arguments.


y Prevent the need to deal with values<0. y Especially problematic in a case of overflow. i.e.: casting an __int64 to int.

Avoid initialization dependencies across compilation units.


y i.e.: Global variables that call others in their

ctor. y Solution: Use the 2-phases ctor pattern.

Avoid providing implicit conversions.


y Make a ctor with one parameter explicit,

unless required.

Good References

If you have the time:


y Effective C++ (3rd Ed.), More Effective C++

and Effective STL \ Scott Meyers y Code Complete, 2nd Ed. \ Steve McConnell

If you dont have the time:


y C++ Coding Standards: 101 Rules,

Guidelines, and Best Practices \ Herb Sutter & Andrei Alexandrescu y The Pragmatic Programmer \ Andrew Hunt & David Thomas

You might also like