The C and C++ Programming Languages

Page presents notes on various C and C++ features, for example C++11 rvalue references, using the C preprocessor for stringization etc etc...

Page Contents

References

  1. Well Known Pre-Define Compiler Macros.
  2. Compiler Explorer
  3. Introducing the Move Constructor, by Smart Bear Software.
  4. C++11 Biggest Changes, by Smart Bear Software.
  5. Distcc - Distributed Compiling

Todo/To Read

  • A Proposal to Add Move Semantics Support to the C++ Language
  • Move Constructors
  • Traits: The else-if-then of Types
  • The Design Is In The Code
  • Generic: Change the Way You Write Exception-Safe Code — Forever
  • Good sockets tutorial - http://beej.us/guide/bgnet/output/html/multipage/ipstructsdata.html
  • http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
  • http://www.alexonlinux.com/signal-handling-in-linux
  • http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html
  • http://www.informit.com/articles/article.aspx?p=397655&seqNum=6
  • https://computing.llnl.gov/tutorials/pthreads/
  • http://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux
  • https://www.freedesktop.org/software/systemd/man/daemon.html
  • http://advancedlinuxprogramming.com/alp-folder/
  • https://linux.die.net/man/3/daemon
  • http://stackoverflow.com/questions/22409780/flock-vs-lockf-on-linux
  • https://balau82.wordpress.com/2010/10/06/trace-and-profile-function-calls-with-gcc/
  • https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
  • https://en.wikipedia.org/wiki/Restrict
  • http://www.inf.ed.ac.uk/teaching/courses/copt/
  • http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html
  • std::find and std::remove to delete from vector (http://stackoverflow.com/questions/39912/how-do-i-remove-an-item-from-a-stl-vector-with-a-certain-value)
  • http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords
  • Casts and inheritance static vs dynamic -- http://ideone.com/J7hUIw
  • Access specifier on inheritance - https://ideone.com/gg19T4
  • https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
  • http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary
  • http://ideone.com/0Ff84V
  • http://stackoverflow.com/questions/4908539/a-way-in-c-to-hide-a-specific-function
  • https://en.wikipedia.org/wiki/Double_dispatch
  • https://en.wikipedia.org/wiki/Virtual_method_table
  • http://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros
  • https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-
  • https://github.com/isocpp/CppCoreGuidelines
  • http://stackoverflow.com/questions/9599807/how-to-add-indention-to-the-stream-operator
  • http://stackoverflow.com/questions/411103/function-with-same-name-but-different-signature-in-derived-class
    and my test http://ideone.com/BPeDtm
  • https://vimeo.com/97337253
  • https://vimeo.com/97337258
  • https://vimeo.com/97329153
  • https://vimeo.com/97318797
  • https://vimeo.com/97315939
  • https://vimeo.com/68390510
  • https://vimeo.com/68390509
  • https://vimeo.com/68390478
  • https://github.com/Kitware/KWStyle
  • http://www.suodenjoki.dk/us/archive/2010/cpp-checkstyle.htm
  • https://stackoverflow.com/questions/5195990/using-boostaccumulators-how-can-i-reset-a-rolling-window-size-does-it-keep-e

Online Work Pads (Compilers and Code Analysers)

The following are quite good online "work pads" for testing out snippets of code and investigating the behaviour of a bit of code across several compilers (or at least versions of).

To compare compilers and view the output assembler try there:

Debugging

Instrumenting Functions

Use GCC compiler option "-finstrument-functions" and implement these functions:

void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));

Valgrind

valgrind \
    --tool=memcheck \
    --track-origins=yes \
    --num-callers=30 \
    --leak-check=full \
    --show-reachable=yes \
    --leak-resolution=high \
    --trace-children=yes \
    -v \
    path/to/binary <args for binary>

Preprocessor Stringization

Stringize Parameter Tokens

To convert the expression passed as a macro parameter to a string use the # operator:

If ... a parameter is immediately preceded by a # ... both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument.

Section 6.10.3.2, C99 standard.

In fact, the standard goes on to mention other conditions such that "#x" is replaced with the result of the pseudo code "strip(escape(collapse_consequtive_whitespace(string(arg)))". The macro argument in the replacement list is first converted to a string. Any consecutive whitspace sequences are converted to just one whitespace, then " is espaced to \", then any preceeding or trailing whitespace is stripped.

It is the above beviour that allows the following (contrived example) to work:

#include <stdio.h>

#define str(x) #x

int main(void) {
	printf(str(jehtech      says "hi" \t to you all));
	return 0;
}
/*
 * Printf preprocesses to (use -E gcc option):
 *    printf("jehtech says \"hi\" \t to you all");
 *                  ^^^    ^^
 *                  ^^^    Notice how " has been replaced with \"
 *                  Notice how whitespace has been collaped
 * OUTPUTS:
 *    jehtech says "hi" <tab-char> to you all
  */

Notice how the whitespace between "jehtech" and "says" has been collapsed into one space and how the " has been escaped to \" (must have been otherwise we'd get a compile error).

#x in a macro replacement list is replaced by the result of the pseudo code "strip(escape(collapse_consequtive_whitespace(string(arg))) "

For (another) example, the following defines (a rather junk, but served to illustrate) assert macro:

#include <stdio.h>

#define ASSERT_EQ(exp, val) \
do { \
   if ((exp) != (val)) \
      fprintf(stderr, "ASSERTION FAILURE: " #exp " != " #val); \
      exit(1); \
} while(0)

int main(void)
{
	ASSERT_EQ(4 + 5, 1);
	return 0;
}
/*
 * Outputs to STDERR:
 *    ASSERTION FAILURE: 4 + 5 != 1
 */

In the macro line fprintf(stderr, "ASSERTION FAILURE: " #exp " != " #val), the parameters exp and val are preceded by a #. The preprocessor evaluated the macro use and replaces #exp with the string containing preprocessing token sequence: "4 + 5". Same for #val. Hence the output of the program.

Glue Parameter Tokens

Another very useful feature is the ability to glue tokens together using ##:

If ... a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument’s preprocessing token sequence ...

Section 6.10.3.3, C99 standard.

One example of how you might "glue" a parameter's token sequence together with other tokens is shown below.

#include <stdio.h>
#include <stddef.h>

#define DEF_STRUCT_FOR_OFFSET(type) \
struct type##OffsetStruct { \
   char dummy; \
   type value; \
}

DEF_STRUCT_FOR_OFFSET(int);
DEF_STRUCT_FOR_OFFSET(long);
DEF_STRUCT_FOR_OFFSET(double);

int main(void)
{
   printf("Alignment required for int is %d bytes\n", offsetof(struct intOffsetStruct, value));
   printf("Alignment required for long is %d bytes\n", offsetof(struct longOffsetStruct, value));
   printf("Alignment required for double is %d bytes\n", offsetof(struct doubleOffsetStruct, value));
   return 0;
}
/*
 * The line "DEF_STRUCT_FOR_OFFSET(int);" expands to:
 *    struct intOffsetStruct { char dummy; int value; };
 *           ^^^
 *           Notice the ## glue at work
 * Same applies to the other similar lines.
 */

The line of interest is "struct type##OffsetStruct. When the preprocessor sees a use of the macro it replaces the parameter "type##" with its tokens. Note, unlike a single # the tokens are not not converted into a string. They are just pasted as tokens in the program. Hence, "DEF_STRUCT_FOR_OFFSET(int)" declares a structure named "intOffsetStruct". Hence the description of ## as "glue".

Note the ## tokens can surround a parameter name, so you can "glue" on both sides.

Summary Of Macro Expansion

Flow diagram describribing how c preprocessor expands macros

Stringize The Result Of Expansion

If we change the example you saw for the stringize example slightly as shown below, we'll get a slightly unexpected outcome:

#include <stdio.h>

#define ASSERT_EQ(exp, val) \
do { \
   if ((exp) != (val)) \
      fprintf(stderr, "ASSERTION FAILURE: " #exp " != " #val); \
      exit(1); \
} while(0)

#define JUNK_SUM (4 + 5)

int main(void)
{
   ASSERT_EQ(JUNK_SUM, 1);
   return 0;
}
/*
 * Outputs to STDERR:
 *    ASSERTION FAILURE: JUNK_SUM != 1
 */

The output is "JUNK_SUM != 1". Why was it this, and not "(4 + 5) != 1"?!

Let's be the preprocessor and follow the flow chart above. We find the macro invocation ASSERT_EQ(JUNK_SUM, 1) and determine that the arguments are exp == JUNK_SUM and val == 1. We now look through the macro's replacement token sequence.

The first place in which arguments are encountered is in the line if ((exp) != (val)). Here neither argument is preceeded by a # or ##, and in the case of a ## neither is followed by a ## either. So, we replace the arguments in the preprocessing token sequence with the arguments fully expanded. Therefore val is replaced with 1. As 1 is just a literal it cannot be expanded further. We reaplce exp with JUNK. This is another macro, so we fully expand that first to get (4+5). This is now fully expanded (but if there had been any macros encountered in the expansion we would have recursively continued to expand everything). Thus exp gets replaced with (4+5) to yield if (((4+5)) != (1)).

That went well. So we keep evaluating the macro's replacement token sequence. we encounter both #exp and #val again, except this time they are both preceeded by a # symbol. So now we would replace #exp with the result of strip(escape(collapse_consequtive_whitespace(string(JUNK))). Ah, we just converted the token JUNK to the string "JUNK". Ooops. Same for #val, that got expanded to the string "1".

Now that all the arguments in the macros replacement list have been expanded we would rescan for more macro names and replace, but now JUNK does not exist as a preprocessing token but as a plain string, so we do nothing more to it. Hence we print out "ASSERTION FAILURE: JUNK_SUM != 1".

So... in summary, the reason is that the preprocessor evaluates/strigizes #exp before expanding out exp. Thus it gets the string "JUNK_SUM".

BUT.... We'd like it to print out "(4 + 5) != 1". How can we accomplish this? The code snippet below shows us how...

#include <stdio.h>

#define xstr(x) str(x)
#define str(x) #x

#define ASSERT_EQ(exp, val) \
do { \
    if ((exp) != (val)) \
       fprintf(stderr, "ASSERTION FAILURE: " xstr(exp) " != " #val); \
       exit(1); \
} while(0)

#define JUNK_SUM (4 + 5)

int main(void)
{
   ASSERT_EQ(JUNK_SUM, 1);
   return 0;
}

Why does it work? In xstr(exp), the argument exp is first replaced to give xstr((4+5)). But the expansion continues until everything is fully expanded out, so now xstr((4+5)) is expanded out to #(4+5). Not this is expanded out to the string "(4+5)". Hence we can print out what was in JUNK_SUM instead of the string "JUNK_SUM". We can apply to same technique for as many levels of macro as the real thing we want to stringize is behind :)

Some Play

Some little playing in C: reading a file line by line and an enhanced strok function.

LValues, RValues etc

LValues

First some terminology. In C, an object is just a region of data storage that represents a value. Why does the standard talk about "data storage"? I think this is because we could mean RAM, a register, ROM or any other kind of memory. It's just a generic term; an abstraction.

In the standard, an expression is a sequence of operators and operands that,

  • computes a value, or
  • results in an object (a region of data that can represent a value), or
  • results in a function, or
  • generates side effects, or
  • is some combination of any of the above

In C & C++ an lvalue is defined as:

An lvalue is an expression with an object type or an incomplete type other than void ... When an object is said to have a particular type, the type is specified by the lvalue used to designate the object ...

... Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue) ...

-- ISO/IEC 9899:1999

What does an expression with an object type mean? It is just an expression that results in an object, i.e., an area of memory we can name (identify) in our program.

An lvalue has to designate an object. This means that an lvalue has to be something that we can use, in our program, to locate an object. I.e. it has to be a name that we can use to access an area of memory that represents a value of some type: it is an object locator. It could also be thought of as an address that is stored into [Ref].

Because an lvalue represents some value in data storage it can persist beyond its current expression. The lvalue represents a way to locate an object (region of data storage).

If we assign into something, we must be assigning into an lvalue because we need to store the value in an object, i.e., an area of data storage that can hold the value and that we can locate via a name in our program. Thus A = B requires that A be an lvalue. It must also be modifiable, so not const!

So, straight away, we can tell that literals are not lvalues. For example the literal 123.321 does is not represented by a region of data storage. It's just a number that exists at compile time. double x = 123.321 is however an expression that creates a region of data storage, refered to by the variable named x. This region of data storage represents the literal 123.321 and is therefore an lvalue.

Also, lets say that a function returns a pointer to an integer, then *(some_function()); must also be an lvalue because it yields the region of data storage that represents a value, even if we don't do anything with it.

An interesting example is this:

int a = 1;
int b = 3;
a + b = 22;

Obviously we can't do this because we intuitively know that one cannot assign a value into an expression because the value a + b is just that, a temporary value. However, this temporary value must exist in memory, even it it is only temporarily in a register.

The variables a and b are lvalues, but they may only exist in a register. But so would the result a + b, so just having some storage isn't quite enough, it would seem.

The answer comes from the second paragraph in the definition: an lvalue [when used as an operand] ... is converted to the value stored in the designated object (and is no longer an lvalue). Ah ha! In the expression a + b, the operands are converted to values and are no longer lvalues, hence the result is not an lvalue. This gives a standards-based explanation of our intuition :)

The important thing to note is that the is no name (designator) that we can use to access the temporary value resulting from a + b, in this case.

And to just be double sure that we're on the right track, Thomas Becker's article C++ Rvalue References Explained has this to say:

An lvalue is an expression that refers to a memory location and allows us to take the address of that memory location via the & operator.

C only really talks about lvalues. Rvalues are mentioned in the standard, but only once: What is sometimes called rvalue is in this International Standard described as the value of an expression. Thus rvalues are just really anything that isn't an lvalue.

Scott Meyers also says a similar thing:

An lvalue is something you can typically make an assignment too, or take its address ... it has a name ...

In Scott Meyer's talk (admittedly about C++ but the same applies for C in the case of lvalues) he gives these examples:

int x = 22;
const int cx = x;

The variable x is an lvalue because it has a name, you can take its address and you can assigned to it.

The variable cx is also an lvalue. You can't assigned to it, but it has a name and you can therefore take its address.

C++11: RValues, RValue References & Universal References

First some references:

C++ has quite a few more types!

An xvalue (an eXpiring value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2).

A glvalue (generalized lvalue) is an lvalue or an xvalue.

An rvalue ... is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

A prvalue (pure rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue ... ]

Oh man! Read the standards docs really isn't easy... eek!

We can gleam that an rvalue is something that is about to expire (its lifetime is over), a temporary object (like the result of A * B, for example) or a value that is not addressable.

This implies it is something that is short lived and won't be used or have side effects almost immediately after its last reference. For example, in the expression a = b * c, the result of b * c is a temporary object and we can't take it's address.

This gives us some idea: rvalues are things we can't really access in our code in any meaningful way. They are transients that exist to accomplish a task. So if b * c involves two matrix classes and they both are large matricies, why copy the result into a? Why not just let a have the resources of the temporary result instead of copying the temporary into a and then destroying the temporary? Could save ourselves a huge copy operation. This is one of the key motivations for rvalue references.

Now though, I'm going to use the referenced articles as the standard isn't something that I would call a "learning/teaching resource". The rest of this is just notes on the referenced, as I'm still getting to grips with the RValue and Universal references!

Expanding on the previous quote by Scott Meyers:

An rvalue, generally speaking, is a temporary object ... Rvalues have no name and you can’t take their address ...

Continuing with Thomas Becker's article...

Move semantics means swapping resource handles between an lvalue and a temporary (rvalue).

If matricies are classes with large data the code matrixA = matrixB * matrixC constructs a temporary object to represent the result of the multiplication and then copies that data into matrixA. A copy has been wasted! The temporary's resources could just be transfered rather than copied!

This needs some kind of "move constructor", a lot like a "copy constructor", but which moves the resources instead of copying them. The type that allows us to do this is the rvalue reference, represented by a double ampersand (&&) (or as Scott Meyers calls them, Universal References because they may actual refer to either an lvalue of an rvalue in some cases):

Matrix& Matrix::operator=(Matrix&& rhs)
//                              ^^
//                              New type: rvalue reference
{
  // ...
  // swap this->mArrayOfValues and rhs.mArrayOfValues
  // ...
}
  • RValue references are prefered by rvalues. LValues prefer lvalue references.
  • RValues allow a function to branch at compile time (via overload resolution) on the condition "Am I being called on an lvalue or an rvalue?"

RValue references are prefered by rvalues. LValues prefer lvalue references. RValues allow a function to branch at compile time (via overload resolution) on the condition "Am I being called on an lvalue or an rvalue?"

MSVC

C/C++ Run Time Library (RTL)

In MSVC projects you can either statically or dynamically link against the run time library. The C and C++ RTL libraries include the standard C/C++ functions that the standards require. So, in C, it is functions like malloc(), memcpy() etc etc, and in C++ it is these and the C++ STL.

When using MSVC, different versions have different RTLs and for each version there are several variants depending on whether you are compiling for debug or release and whether you static vs dynamic linking. Note: there are only multi-threaded libraries available (there used to be single threaded but no more).

To statically link against the RTL implies that the RTL code is linked into your program so that your program does not have any external dependencies as far as using the C/C++ standard library functions goes.

To dynamically link against the RTL means that your program is compiled without the RTL "backed in" and thus requires a certain set of DLLs, which must be present on the host when your program is executed.

The former has the advantage that you don't care whether your host has the correct RTL installed (because your program already contains all the RTL functions it needs) but the disadvantage that it is slightly bigger. The latter has the advantage that it will be slightly smaller (and if there was a patch etc to the RTL you wouldn't have to redistribute your app), but it has the disandvantage that the host must have the correct RTL DLLs available and if it doesn't you have to distribute them.

In debug libraries, the debug symbols are generated (.pdb) files and no opimization is used. In release libraries, symbols are stripped and code optimization is used.

Your link options are [Ref]:

  1. /MD[d]:Use multi-threaded dynamic RTL. No 'd' for release, 'd' for debug.
  2. /MT[d]:Use multi-threaded static RTL. No 'd' for release, 'd' for debug.

Screenshot of MSVC++ 2015 project properties and where to find the Runtime Library settings

Casting in C & C++

C v.s. C++

In C there is no checking done when you make a cast. You can cast from any type to another and the compiler will not complain. In C++, C-style casts should be avoided because the C++ casts offer a safer way to cast.

Casts Are More Than Treating One Type As Another!

Interestingly a cast may do more than just "switching" types. The compiler may have to generate extra code to achieve this!

Many programmers believe that casts do nothing but tell compilers to treat one type as another, but this is mistaken. Type conversions of any kind (either explicit via casts or implicit by compilers) often lead to code that is executed at runtime.

This chapter is particularly illumiating. It explains why dynamic_casts can be "expensive" - many compilers will do string compares on class names to perform the RTTI. I guess they might store a type variable behind the scenes that the compiler generate code to check against. (Need to reed up on this lol)

Static & Reinterpret Casts

A static cast converts betwen related types, but will not allow you to convert between unrelated types. For example, a static cast will not cast away constness or volatility.

When you static_cast you're basically saying to the compiler that you guarantee that the type is what you say it is. This means, especially for down-casts from base classes to child classes, the compiler won't emmit code to do run time checks. Thus static_cast is less safe. It may still emmit code to do the cast, just not the type checking code.

Reinterpret casts are even more unsafe...

Unlike static_cast, but like const_cast, the reinterpret_cast expression does not compile to any CPU instructions. It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the [new type].

-- cppreference.com

IOStreams

Output Stream Manipulators

Manipulators are objects known to IOStream that allows a stream to be changed. Include <iomanip>. Mostly, states are persistent.

cout.put(c)Write char c to stdout.
std::endlWrites a newline ("\n") then calls cout.flush(). Note this is not a cross platform newline which is sometimes a confusion. It just outputs "\n", not "\r\n" or anything else.
std::flushCalls cout.flush().
std::endsPrints NULL character to cout.
setw(c)Sets c as the stream's fill character.
setfill()Sets field width. Default is right aligned.
cout.setf(flag-to-set, flag-to-clear)flag-to-clear, the second parameter clears all flags before setting flag-to-set.
cout.unsetf(flag-to-clear)Clear a flag.
ios::hex ios::oct ios::decFor integer output.
ios::basefieldMask to clear all integer output formats.
ios::showbasePuts a "0x" in front of hex output etc.
ios::showposShows the positive sign for values.
cout.precision()Sets precision of floating point output.
ios::fixed ios::scientific
ios:uppercaseForce hexadecimal alpha characters to uppercase.
ios:leftSets left alignment when field width greater than width of whats being printed.
ios::adjustfieldMask to clear all alignments.
(void *)Cast any pointer to void * to print the pointer

Input Streams

By default input streams ignore whitespace.

Usually line buffered. I.e. cin >> var; will not return until RETURN is pressed.

Quietly go into a safe, do-nothing, mode upon error.

Google Test (On Windows)

Jeez it took ages to set this bugger up... so save yourself some time and don'try to open the existing msvc project files and instead re-generate them using cmake! I promise you it will save you the heart-ache. These are the steps:

  1. Download and install CMake and make sure you select the option to put CMake on the path
  2. Pick a root directory and clone the CMake git repo there. I'm gonna use C:\Users\jehtech\googletest_msvc. Therefore from the git command prompt naviage to /c/users/jehtech/googletest_msvc and type git clone git@github.com:google/googletest.git. This will create the subdirectory googletest.
  3. Absolutely ignore the existing MSVC project files in C:\Users\jehtech\googletest_msvc\googletest\googletest\msvc!!
  4. From the same directory, but in your normal console, type cmake -Dgtest_build_samples=ON googletest_msvc. Using -Dgtest_build_samples=ON tells CMake to generate project files that contain the Google Test examples as well.
  5. CMake should now generate your MSVC project files for you in the directory C:\Users\jehtech\googletest_msvc.
  6. Load the project file googletest-distribution.sln and build the solution for both Debug and Release. This will create the directories C:\Users\James\googletest_msvc\googlemock\gtest\{Debug,Release} that contain the built gtest libraries.

But annoyingly I still get the following when trying to create my own project, although the sample tests do not seem to have this problem for some reason.

Severity	Code	Description	Project	File	Line	Suppression State
Error	C2440	'': cannot convert from 'initializer list' to 'testing::internal::AssertHelper'	test_mpeg	c:\users\james\documents\git\mpeg_ts_messing\gtest\src\gtest_binary_buffer.cpp	12	
Severity	Code	Description	Project	File	Line	Suppression State
Error	C2065	'gtest_ar': undeclared identifier	test_mpeg	c:\users\james\documents\git\mpeg_ts_messing\gtest\src\gtest_binary_buffer.cpp	12	
Severity	Code	Description	Project	File	Line	Suppression State
Error	C2589	'switch': illegal token on right side of '::'	test_mpeg	c:\users\james\documents\git\mpeg_ts_messing\gtest\src\gtest_binary_buffer.cpp	12	
Severity	Code	Description	Project	File	Line	Suppression State
Error	C2181	illegal else without matching if	test_mpeg	c:\users\james\documents\git\mpeg_ts_messing\gtest\src\gtest_binary_buffer.cpp	12

Smart Pointers

Defined in <memory>

Shared Pointers

For shared ownership use shared_ptr. You can have many shared pointers pointing at the same object. That object is only freed when the number of pointers to the object reaches 0.

For shared use where ownership is not required weak_ptr is used.

#include <memory>
#include <iostream>
#include <vector>

class Transformer 
{
protected:
   std::string mName;
public:
   Transformer(const std::string &name) : mName(name) { }
   std::string GetName() { return mName; }
};

class Autobot : public Transformer 
{ 
public:
   Autobot(const std::string &name) : Transformer(name) { }
   ~Autobot() { std::cout << "** Deleting Autobot " << mName << std::endl; }
};

class Decepticon : public Transformer 
{
public:
   Decepticon(const std::string &name) : Transformer(name) { }
   ~Decepticon() { std::cout << "** Deleting Decepticon " << mName << std::endl; }
};

int main(int argc, char *argv[])
{
   // Note in C++11 No longer need space between two template endings: >> not >space>
   std::vector<std::shared_ptr<Transformer>> characters;
   std::shared_ptr<Transformer> pOptimusPrime(new Autobot("OptimusPrime"));
   std::shared_ptr<Transformer> pBumblebee(new Autobot("Bumblebee"));

   {
      std::shared_ptr<Transformer> pMegatron(new Decepticon("Megatron"));

      std::cout << "Before vector insertion:\n" 
                   "   Optimus has " << pOptimusPrime.use_count() << " owners\n" 
                   "   Bumblebee has " << pBumblebee.use_count() << " owners\n" 
                   "   Megatron has " << pMegatron.use_count() << " owners\n";

      characters.push_back(pOptimusPrime);
      characters.push_back(pOptimusPrime);
      characters.push_back(pBumblebee);
      characters.push_back(pMegatron);
      characters.push_back(pOptimusPrime);
      characters.push_back(pMegatron);

      std::cout << "After vector insertion:\n" 
                   "   Optimus has " << pOptimusPrime.use_count() << " owners\n" 
                   "   Bumblebee has " << pBumblebee.use_count() << " owners\n" 
                   "   Megatron has " << pMegatron.use_count() << " owners\n";

      std::cout << "\n"
                   "Now we'll remove the evil Megatron from the list\n";
      for(auto it = characters.begin(); it != characters.end(); )
      {
         if((*it)->GetName() == "Megatron")
            it = characters.erase(it);
         else
            ++it;
      }

      std::cout << "\n"
                   "Removing Megatron from the list means that..\n";

                   std::cout << "Megatron has " << pMegatron.use_count() << " owners\n"
                                "Now only pMegatron holds a reference. As we go out\n"
                                "of scope Megatron will die!\n";
   }

   std::cout << "\n"
                "Thankfully our other heros survived.";

   std::cout << "\n"
                "Because our heros are in the list, we can empty the original\n"
                "smart pointers and they will continue to exist...\n";

   pOptimusPrime.reset();
   pBumblebee.reset();


   std::cout << "\n"
                "Now we exit, Optimus and Megatron should also be\n"
                "destroyed (noooo, Optimus!)\n";

   return 0;
}
/*
OUTPUT IS:

Before vector insertion:
   Optimus has 1 owners
   Bumblebee has 1 owners
   Megatron has 1 owners
After vector insertion:
   Optimus has 4 owners
   Bumblebee has 2 owners
   Megatron has 3 owners

Now we'll remove the evil Megatron from the list

Removing Megatron from the list means that..
Megatron has 1 owners
Now only pMegatron holds a reference. As we go out
of scope Megatron will die!
** Deleting Decepticon Megatron

Thankfully our other heros survived.
Because our heros are in the list, we can empty the original
smart pointers and they will continue to exist...

Now we exit, Optimus and Megatron should also be
destroyed (noooo, Optimus!)
** Deleting Autobot Bumblebee
** Deleting Autobot OptimusPrime
*/

Templates

Calling Functions In a Templated Base Class - Gotcha!

This one really surprised me! When you inherit from a base class that is a template beware calling base class functions from the derivied class. The functions names are not looked up as you'd expect (or at least how I'd have expected lol).

If in doubt, always prefix base-class function calls with "this->"!

#include <iostream>
using namespace std;

void bar()
{
   std::cout << "Gloal bar()\n";
}

template <typename T>
class Base
{
public:
   void bar()
   {
      std::cout << "Template bar()\n";
   }
};

template <typename T>
class Derived : Base<T>
{
public:
   void foo()
   {
      bar(); // WARNING! Does NOT do what you might expect!
      this->bar();
      Base<T>::bar();
   }
};

int main()
{
   Derived<int> d;
   d.foo();
   return 0;
}

/* OUTPUTS:
Gloal bar()
Template bar()
Template bar()
*/

Vectors

Erasing Elements

If you don't want to use remove_if() use the following...

myVector::iterator itr = myVector.begin();
myVector::iterator itrEnd = myVector.end();
while(itr != itrEnd)
{
    if (delete_condition)
    {
        it = v.erase(it);
    }
    else
    {
        ++it;
    }
}

If it is a simple find-by-some-condition and you are using C++11 use:

#include <algorithm>
myVector.erase(
    std::remove_if(
        myVector.begin(), myVector.end(), [](T const & x) -> bool { /* Code here */ }),
    myVector.end());

But, of course, you might not be using C++11, in which case use a callable instead of the lambda. This can be a function or a structure implementing the call operator. Example below:

class MyComparitor
{
public:
    MyComparitor
    (
        std::string needle
    ) : mNeedle(needle)
    {
    }

    bool operator()(const MyObject *const obj) const
    {
        return obj->someProperty == mNeedle;
    }
private:
    std::string mNeedle;
};

myVector.erase(
    std::remove_if(
        myVector.begin(), myVector.end(), MyComparitor("String to find"));
    		

You may be wondering if the order of evaluation of the vec.erase() parameter vec.end() (repeated twice) matters. The answer is it does not. The reason is that std::remove() does not change the size of vec. The remove operation works by moving elements around so that to the left of the returned new end iterator is the new contents and to the right (and including) is effectively invalid. Hence the end iterator does not change: the location remains the same, it's just the contents that differs!

Note that, particularly for vectors, this erase-remove idiom would be a lot faster than removing each matching element individualy, if there is more than one such element. The reason is that removing each element individually requires every element "to the right" in the vector's array to be moved left by one. Therefore, if there are n targets, you do n swaps rather than n removes and array reshuffles (a lot more work!).

We can look at this a little more closely by just looking at what remove() does...

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>

template<typename T>
void PrintElements(const std::string &prefix, const T &container, const unsigned int width=3)
{
   std::cout < prefix;
   for (const auto &elem : container) std::cout < std::setw(width) < std::right < elem;
   std::cout <lt; std::endl;
}

template<typename T>
void PrintEnd(const std::string &prefix, T itA, T itB, const unsigned int width=3)
{
   auto dist = (std::distance(itA, itB) + 1u) * width + prefix.size() + 1u;
   std::cout <lt; std::setw(dist) <lt; std::right <lt; "^\n";
}

int main(int argc, char *argv[])
{
   std::vector testVec = { 1, 10, 2, 10, 3, 10, 4, 10, 5, 10, 6 };

   PrintElements("Before remove: ", testVec);
   PrintEnd("Before remove: ", testVec.begin(), testVec.end());

   auto newEnd = std::remove(testVec.begin(), testVec.end(), 10);
   PrintElements("After remove:  ", testVec);
   PrintEnd("After remove:  ", testVec.begin(), newEnd);

   testVec.erase(testVec.begin(), newEnd);
   PrintElements("After erase:   ", testVec);
   PrintEnd("After erase:   ", testVec.begin(), testVec.end());

   return 0;
}
/* 
 * OUTPUTS:
 * Before remove:   1 10  2 10  3 10  4 10  5 10  6
 *                                                   ^
 * After remove:    1  2  3  4  5  6  4 10  5 10  6
 *                                    ^
 * After erase:     4 10  5 10  6
 *                                 ^
 */