C++

STL Objects and Win32 Module Boundaries
C++ c++ stl win32
Published: 2008-01-04
STL Objects and Win32 Module Boundaries
Let’s say you have the following function: 1 2 3 4 void AppendChar(std::string& s, char ch) { s += ch; } What happens if this function is exported as an ordinal function from a DLL (not an inlined piece of code inside a header) and you call it from an EXE? It works most of the time. When it doesn’t, it corrupts your heap and causes a spectacular mess. Read more...
Converting C++ Member Functions into Function Objects
C++ c++ stl
Published: 2007-08-28
Converting C++ Member Functions into Function Objects
Let’s say you have a C++ function that takes a function object as a parameter and calls it: 1 2 3 4 5 template <typename _Fn> void call_functor(_Fn fn) { fn(); } Now let’s say you want to pass a class’s member function to call_functor() above, as in: 1 2 3 4 5 6 7 class C { void foo() { std::cout << "foo()\n"; } }; C c; call_functor(/\* What do I put here? Read more...
STL Map Use
C++ c++ stl
Published: 2007-01-25
STL Map Use
What’s wrong with the following code? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 template<typename T1, typename T2> struct my_pair { typedef T1 first_type; typedef T2 second_type; my_pair() : first(T1()), second(T2()) {} my_pair(const T1& v1, const T2& v2) : first(v1), second(v2) {} T1 first; T2 second; }; template<typename T1, typename T2> inline bool operator< ( const my_pair<T1, T2>& x, const my_pair<T1, T2>& y ) { return (x. Read more...
STL Vector Use
C++ c++ stl
Published: 2007-01-23
STL Vector Use
I recently wrote a piece of code that looked something like the following: 1 2 3 4 5 6 7 8 9 10 11 static const int NUM_TOTAL_VALUES = ...; typedef ... T; // Create vec and reserve NUM_TOTAL_VALUES spaces for later insertion std::vector<T> vec(NUM_TOTAL_VALUES); // Insert values into vec for (int i = 0; i != NUM_TOTAL_VALUES; ++i) vec.push_back(...); // vec should now have NUM_TOTAL_VALUES values in it (but doesn't! Read more...
Managed Wrappers and Hidden Interdependencies
C++ c++ managed c++
Published: 2007-01-10
Managed Wrappers and Hidden Interdependencies
Let’s say you have the following unmanaged code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #pragma unmanaged class Stream { ... }; // Conceptual stream class class StreamWriter { public: StreamWriter(Stream* pStream) : m_pStream(pStream) {} ~StreamWriter() { /* Use m_pStream in some way */ } ... private: Stream* m_pStream; }; void f() { Stream stream; StreamWriter streamWriter(&stream); // Use streamWriter // streamWriter is destroyed // stream is destroyed } Note that StreamWriter’s destructor uses m_pStream (perhaps by flushing the stream). Read more...
C++ Exception Handling
C++ c++
Published: 2006-01-30
C++ Exception Handling
Quick quiz: What is the behavior of the following code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> int main(int argc, char* argv[]) { try { *((char*) 0) = 1; } catch (...) { printf("Caught exception.\n"); } return 0; } Surprisingly, it depends! As I would expect, on many operating system / compiler combinations (such as gcc version 3. Read more...
Avoid Atoi() And Similar Functions
C++ c
Published: 2005-09-13
Avoid Atoi() And Similar Functions
Avoid atoi() and related functions: they do not distinguish between invalid input and a valid “0″ string. Use functions which properly report errors, such as strtod().
Be Careful With Doubles And C++ Streams
C++ c++
Published: 2005-09-12
Be Careful With Doubles And C++ Streams
I ran across a piece of code recently that was using ostrstream to convert a double to a string. The code looked something like: 1 2 3 4 5 6 7 std::string DoubleToString(double d) { std::ostrstream ostr; ostr << d << std::ends; std::string str(ostr.str()); ostr.freeze(false); return str; } This function was used to convert doubles to strings for insertion into an XML document, which were eventually parsed in an XSLT by the XPath number() function. Read more...
Use RAII
C++ c++ win32
Published: 2005-09-09
Use RAII
This is covered by any halfway-decent C++ book, but I believe it deserves reiteration: Use the RAII idiom. I don’t think I could explain RAII any better than HackCraft does in The RAII Programming Idiom. Let me demonstrate how to use RAII with a semi-contrived example. Here’s the pre-RAII code: 1 2 3 4 5 6 7 8 9 HMODULE hm = LoadLibrary(_T("user32.dll")); if (hm != NULL) { FARPROC proc = GetProcAddress(hm, "MessageBoxW"); if (proc ! Read more...
Be Careful With Bitfields
C++ c win32
Published: 2005-09-07
Be Careful With Bitfields
Consider the following piece of code (adapted from a real-world bug): 1 2 3 4 5 6 7 BOOL IsDirectory(LPCTSTR strPathName) { DWORD dwAtts = GetFileAttributes(strPathName); if (dwAtts == INVALID_FILE_ATTRIBUTES) return FALSE; return (dwAtts == FILE_ATTRIBUTE_DIRECTORY); } This function will work most of the time, but every now and again it will run across a directory which it will claim isn’t one. Why? The problem is caused because dwAtts is a bitfield (see the GetFileAttributes() documentation). Read more...
Use Constant References For Input-Only Parameters, Pointers Otherwise
C++ c++
Published: 2005-09-06
Use Constant References For Input-Only Parameters, Pointers Otherwise
This is a style issue, so there is no right or wrong, but I suggest using a const reference for an input-only paramater to a C++ function and a pointer for an input/output or output-only parameter. This makes it slightly more obvious that the parameter might be modified by the function. Example: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ReturnType Function ( const ParamType& inputParam, ParamType* inputOutputParam, ParamType* outputParam ) { // . Read more...
Write Functions Which Take Iterators, Not Collections
C++ c++ stl
Published: 2005-09-05
Write Functions Which Take Iterators, Not Collections
If my experience is typical, this is a very common construct: 1 2 3 4 5 6 7 8 9 10 11 12 13 ReturnType Function ( const std::vector<T>& container ) { typedef std::vector<T>::const_iterator iterator_t; for (iterator_t iter = container.begin(); iter != container.end(); ++iter) { // Work with *iter } } The problem with this construct is that you have forced a container choice upon the user of your function. Read more...
Prefer Iteration To Indexing
C++ c++ stl
Published: 2005-09-02
Prefer Iteration To Indexing
I’ve seen the following STL construct countless times: 1 2 3 4 std::vector<T> container; for (int i = 0; i < container.size(); ++i) { // Work with container[i] } Unless otherwise necessary, it is better to use an STL iterator because it enables you to more easily change the underlying container. You can isolate the code changes required to one line by using typedef, as in: 1 2 3 4 5 6 7 8 9 10 typedef std::vector<T> container_t; container_t container; // Or ::const_iterator as necessary for (container_t::iterator iter = container. Read more...