Best c++ questions in January 2011

How can I know which parts in the code are never used?

130 votes

I have legacy C++ code that I'm supposed to remove unused code from. The problem is that the code base is large.

How can I find out which code is never called/never used?

There are two varieties of unused code:

  • the local one, that is, in some functions some paths or variables are unused (or used but in no meaningful way, like written but never read)
  • the global one: functions that are never called, global objects that are never accessed

For the first kind, a good compiler can help:

  • -Wunused (GCC, Clang) should warn about unused variables, Clang unused analyzer has even been incremented to warn about variables that are never read (even though used).
  • -Wunreachable-code (GCC) should warn about local blocks that are never accessed (it happens with early returns or conditions that always evaluate to true)
  • there is no option I know of to warn about unused catch blocks, because the compiler generally cannot prove that no exception will be thrown.

For the second kind, it's much more difficult. Statically it requires whole program analysis, and even though link time optimization may actually remove dead code, in practice the program has been so much transformed at the time it is performed that it is near impossible to convey meaningful information to the user.

There are therefore two approaches:

  • The theoretic one is to use a static analyzer. A piece of software that will examine the whole code at once in great detail and find all the flow paths. In practice I don't know any that would work here.
  • The pragmatic one is to use an heuristic: use a code coverage tool (in the GNU chain it's gcov. Note that specific flags should be passed during compilation for it to work properly). You run the code coverage tool with a good set of varied inputs (your unit-tests or non-regression tests), the dead code is necessarily within the unreached code... and so you can start from here.

If you are extremely interested in the subject, and have the time and inclination to actually work out a tool by yourself, I would suggest using the Clang libraries to build such a tool.

  1. Use the Clang library to get an AST (abstract syntax tree)
  2. Perform a mark-and-sweep analysis from the entry points onward

Because Clang will parse the code for you, and perform overload resolution, you won't have to deal with the C++ languages rules, and you'll be able to concentrate on the problem at hand.

However this kind of technique cannot identify the virtual overrides that are unused, since they could be called by third-party code you cannot reason about.

Which one will execute faster, if (flag==0) or if (0==flag)?

70 votes

Interview question: Which one will execute faster, if (flag==0) or if (0==flag)? Why?

I haven't seen any correct answer yet (and there are already some) caveat: Nawaz did point out the user-defined trap. And I regret my hastily cast upvote on "stupidest question" because it seems that many did not get it right and it gives room for a nice discussion on compiler optimization :)

The answer is:

What is flag's type?

In the case where flag actually is a user-defined type. Then it depends on which overload of operator== is selected. Of course it can seem stupid that they would not be symmetric, but it's certainly allowed, and I have seen other abuses already.

If flag is a built-in, then both should take the same speed.

From the Wikipedia article on x86, I'd bet for a Jxx instruction for the if statement: perhaps a JNZ (Jump Near if not zero) or some equivalent.

I'd doubt the compiler misses such an obvious optimization, even with optimizations turned off. This is the type of things for which Peephole Optimization is designed for.

EDIT: Sprang up again, so let's add some assembly (LLVM 2.7 IR)

int regular(int c) {
  if (c == 0) { return 0; }
  return 1;
}

int yoda(int c) {
  if (0 == c) { return 0; }
  return 1;
}

define i32 @regular(i32 %c) nounwind readnone {
entry:
  %not. = icmp ne i32 %c, 0                       ; <i1> [#uses=1]
  %.0 = zext i1 %not. to i32                      ; <i32> [#uses=1]
  ret i32 %.0
}

define i32 @yoda(i32 %c) nounwind readnone {
entry:
  %not. = icmp ne i32 %c, 0                       ; <i1> [#uses=1]
  %.0 = zext i1 %not. to i32                      ; <i32> [#uses=1]
  ret i32 %.0
}

Even if one does not know how to read the IR, I think it is self explanatory.

Is main() really start of a C++ program?

56 votes

The section $3.6.1/1 from the C++ Standard reads,

A program shall contain a global function called main, which is the designated start of the program.

Now consider this code,

int square(int i) { return i*i; }
int user_main()
{ 
    for ( int i = 0 ; i < 10 ; ++i )
           std::cout << square(i) << endl;
    return 0;
}
int main_ret= user_main();
int main() 
{
        return main_ret;
}

This sample code does what I intend it to do, i.e printing the square of integers from 0 to 9, before entering into the main() function which is supposed to be the "start" of the program.

Have a look at the output here : http://www.ideone.com/Niy0R

I also compiled it with -pedantic option, GCC 4.5.0. It gives no error, not even warning!

So my question is,

Is this code really Standard conformant?

If it's standard conformant, then does it not invalidate what the Standard says? main() is not start of this program! user_main() executed before the main().

I understand that to initialize the global variable main_ret, the use_main() executes first but that is a different thing altogether; the point is that, it does invalidate the quoted statement $3.6.1/1 from the Standard, as main() is NOT the start of the program; it is in fact the end of this program!


EDIT:

How do you define the word 'start'?

It boils down to the definition of the phrase "start of the program". So how exactly do you define it?

No, C++ does a lot of things to "set the environment" prior to the call of main; however, main is the official start of the "user specified" part of the C++ program.

Some of the environment setup is not controllable (like the initial code to set up std::cout; however, some of the environment is controllable like static global blocks (for initializing static global variables). Note that since you don't have full control prior to main, you don't have full control on the order in which the static blocks get initialized.

After main, your code is conceptually "fully in control" of the program, in the sense that you can both specify the instructions to be performed and the order in which to perform them. Multi-threading can rearrange code execution order; but, you're still in control with C++ because you specified to have sections of code execute (possibly) out-of-order.

Are C++ enums slower to use than integers?

49 votes

It's really a simple problem :

I'm programming a Go program. Should I represent the board with a QVector<int> or a QVector<Player> where

enum Player
{
    EMPTY = 0,
    BLACK = 1,
    WHITE = 2
};

I guess that of course, using Player instead of integers will be slower. But I wonder how much more, because I believe that using enum is better coding.

I've done a few tests regarding assigning and comparing Players (as opposed to int)

QVector<int> vec;
vec.resize(10000000);
int size = vec.size();


for(int i =0; i<size; ++i)
{
    vec[i] = 0;
}


for(int i =0; i<size; ++i)
{
    bool b = (vec[i] == 1);
}


QVector<Player> vec2;
vec2.resize(10000000);
int size = vec2.size();


for(int i =0; i<size; ++i)
{
    vec2[i] = EMPTY;
}


for(int i =0; i<size; ++i)
{
    bool b = (vec2[i] == BLACK);
}

Basically, it's only 10% slower. Is there anything else I should know before continuing?

Thanks!

Enums are completely resolved at compile time (enum constants as integer literals, enum variables as integer variables), there's no speed penalty in using them.

In general the average enumeration won't have an underlying type bigger than int (unless you put in it very big constants); in facts, at §7.2 ¶ 5 it's explicitly said:

The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.

You should use enumerations when it's appropriate because they usually make the code easier to read and to maintain (have you ever tried to debug a program full of "magic numbers"? :S).

As for your results: probably your test methodology doesn't take into account the normal speed fluctuations you get when you run code on "normal" machines1; have you tried running the test many (100+) times and calculating mean and standard deviation of your times? The results should be compatible: the difference between the means shouldn't be bigger than 1 or 2 times the RSS2 of the two standard deviations (assuming, as usual, a Gaussian distribution for the fluctuations).

Another check you could do is to compare the generated assembly code (with g++ you can get it with the -S switch).


  1. On "normal" PCs you have some indeterministic fluctuations because of other tasks running, cache/RAM/VM state, ...
  2. Root Sum Squared, the square root of the sum of the squared standard deviations.

33 votes

C++ inherited arrays from C where they are used virtually everywhere. C++ provides abstractions that are easier to use and less error-prone (std::vector<T> since C++98 and std::array<T, n> since C++0x), so the need for arrays does not arise quite as often as it does in C. However, when you read legacy code or interact with a library written in C, you should have a firm grasp on how arrays work.

This FAQ is split into four parts:

  1. arrays on the type level and accessing elements
  2. array creation and initialization
  3. assignment and parameter passing
  4. multidimensional arrays and arrays of pointers

If you feel I have missed something important, write an answer and link it here as an additional part.

In the following text, "array" means "C array", not the class template std::array. Basic knowledge of the C declarator syntax is assumed. Note that the manual usage of new and delete as demonstrated below is extremely dangerous in the face of exceptions, but that is the topic of another FAQ.

(Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)

Arrays on the type level

An array type is denoted as T[n] where T is the element type and n is a positive size, the number of elements in the array. The array type is a product type of the element type and the size. If one or both of those ingredients differ, you get a distinct type:

#include <type_traits>

static_assert(!std::is_same<int[8], float[8]>::value, "distinct element type");
static_assert(!std::is_same<int[8],   int[9]>::value, "distinct size");

Note that the size is part of the type, that is, array types of different size are incompatible types that have absolutely nothing to do with each other. sizeof(T[n]) is equivalent to n * sizeof(T).

Array-to-pointer decay

The only "connection" between T[n] and T[m] is that both types can implicitly be converted to T*, and the result of this conversion is a pointer to the first element of the array. That is, anywhere a T* is required, you can provide a T[n], and the compiler will silently provide that pointer:

                  +---+---+---+---+---+---+---+---+
the_actual_array: |   |   |   |   |   |   |   |   |   int[8]
                  +---+---+---+---+---+---+---+---+
                    ^
                    |
                    |
                    |
                    |  pointer_to_the_first_element   int*

This conversion is known as "array-to-pointer decay", and it is a major source of confusion. The size of the array is lost in this process, since it is no longer part of the type (T*). Pro: Forgetting the size of an array on the type level allows a pointer to point to the first element of an array of any size. Con: Given a pointer to the first (or any other) element of an array, there is no way to detect how large that array is or where exactly the pointer points to relative to the bounds of the array. Pointers are extremely stupid.

Arrays are not pointers

The compiler will silently generate a pointer to the first element of an array whenever it is deemed useful, that is, whenever an operation would fail on an array but succeed on a pointer. This conversion from array to pointer is trivial, since the resulting pointer value is simply the address of the array. Note that the pointer is not stored as part of the array itself (or anywhere else in memory). An array is not a pointer.

static_assert(!std::is_same<int[8], int*>::value, "an array is not a pointer");

One important context in which an array does not decay into a pointer to its first element is when the & operator is applied to it. In that case, the & operator yields a pointer to the entire array, not just a pointer to its first element. Although in that case the values (the addresses) are the same, a pointer to the first element of an array and a pointer to the entire array are completely distinct types:

static_assert(!std::is_same<int*, int(*)[8]>::value, "distinct element type");

The following ASCII art explains this distinction:

      +-----------------------------------+
      | +---+---+---+---+---+---+---+---+ |
+---> | |   |   |   |   |   |   |   |   | | int[8]
|     | +---+---+---+---+---+---+---+---+ |
|     +---^-------------------------------+
|         |
|         |
|         |
|         |  pointer_to_the_first_element   int*
|
|  pointer_to_the_entire_array              int(*)[8]

Note how the pointer to the first element only points to a single integer (depicted as a small box), whereas the pointer to the entire array points to an array of 8 integers (depicted as a large box).

The same situation arises in classes and is maybe more obvious. A pointer to an object and a pointer to its first data member have the same value (the same address), yet they are completely distinct types.

If you are unfamiliar with the C declarator syntax, the parenthesis in the type int(*)[8] are essential:

  • int(*)[8] is a pointer to an array of 8 integers
  • int*[8] is an array of 8 pointers to an integer

Accessing elements

C++ provides two syntactic variations to access individual elements of an array. Neither of them is superior to the other, and you should familiarize yourself with both.

Pointer arithmetic

Given a pointer p to the first element of an array, the expression p+i yields a pointer to the i-th element of the array. By dereferencing that pointer afterwards, one can access individual elements:

std::cout << *(x+3) << ", " << *(x+7) << std::endl;

If x denotes an array, then array-to-pointer decay will kick in, because adding an array and an integer is meaningless (there is no plus operation on arrays), but adding a pointer and an integer makes sense:

   +---+---+---+---+---+---+---+---+
x: |   |   |   |   |   |   |   |   |   int[8]
   +---+---+---+---+---+---+---+---+
     ^           ^               ^
     |           |               |
     |           |               |
     |           |               |
x+0  |      x+3  |          x+7  |     int*

(Note that the implicitly generated pointer has no name, so I wrote x+0 in order to identify it.)

If, on the other hand, x denotes a pointer to the first (or any other) element of an array, then array-to-pointer decay is not necessary, because the pointer on which i is going to be added already exists:

   +---+---+---+---+---+---+---+---+
   |   |   |   |   |   |   |   |   |   int[8]
   +---+---+---+---+---+---+---+---+
     ^           ^               ^
     |           |               |
     |           |               |
   +-|-+         |               |
x: | | |    x+3  |          x+7  |     int*
   +---+

Note that in the depicted case, x is a pointer variable (discernible by the small box next to x), but it could just as well be the result of a function returning a pointer (or any other expression of type T*).

Indexing operator

Since the syntax *(x+i) is a bit clumsy, C++ provides the alternative syntax x[i]:

std::cout << x[3] << ", " << x[7] << std::endl;

Due to the fact that addition is commutative, the following code does exactly the same:

std::cout << 3[x] << ", " << 7[x] << std::endl;

The definition of the indexing operator leads to the following interesting equivalence:

&x[i]  ==  &*(x+i)  ==  x+i

However, &x[0] is generally not eqivalent to x. The former is a pointer, the latter an array. Only when the context triggers array-to-pointer decay can x and &x[0] be used interchangeably. For example:

T* p = &array[0];   // rewritten as *(array+0), decay happens due to the addition
T* q = array;       // decay happens due to the assignment

On the first line, the compiler detects an assignment from a pointer to a pointer, which trivially succeeds. On the second line, it detects an assigment from an array to a pointer. Since this is meaningless (but pointer to pointer assignment makes sense), array-to-pointer decay kicks in as usual.

Ranges

An array of type T[n] has n elements, indexed from 0 to n-1; there is no element n. And yet, to support half-open ranges (where the beginning is inclusive and the end is exclusive), C++ allows the computation of a pointer to the (non-existent) n-th element, but it is illegal to dereference that pointer:

   +---+---+---+---+---+---+---+---+....
x: |   |   |   |   |   |   |   |   |   .   int[8]
   +---+---+---+---+---+---+---+---+....
     ^                               ^
     |                               |
     |                               |
     |                               |
x+0  |                          x+8  |     int*

For example, if you want to sort an array, both of the following would work equally well:

std::sort(x + 0, x + n);
std::sort(&x[0], &x[0] + n);

Note that it is illegal to provide &x[n] as the second argument since this is equivalent to &*(x+n), and the subexpression *(x+n) technically invokes undefined behavior in C++ (but not in C99).

Also note that you could simply provide x as the first argument. That is a little too terse for my taste, and it also makes template argument deduction a bit harder for the compiler, because in that case the first argument is an array but the second argument is a pointer. (Again, array-to-pointer decay kicks in.)

Rule-of-Three becomes Rule-of-Five with C++0x?

31 votes

So, after watching this wonderful lecture on rvalue references, I thought that every class would benefit of such a "move constructor", template<class T> MyClass(T&& other) edit and of course a "move assignment operator", template<class T> MyClass& operator=(T&& other) as Philipp points out in his answer, if it has dynamically allocated members, or generally stores pointers. Just like you should have a copy-ctor, assignment operator and destructor if the points mentioned before apply. Thoughts?

I'd say the Rule of Three becomes the Rule of Three, Four and Five:

Each class should explicitly define exactly one of the following set of special member functions:

  • None
  • Destructor, copy constructor, copy assignment operator

In addition, each class that explicitly defines a destructor may explicitly define a move constructor and/or a move assignment operator.

Usually, one of the following sets of special member functions is sensible:

  • None (for many simple classes where the implicitly generated special member functions are correct and fast)
  • Destructor, copy constructor, copy assignment operator (in this case the class will not be movable)
  • Destructor, move constructor, move assignment operator (in this case the class will not be copyable, useful for resource-managing classes where the underlying resource is not copyable)
  • Destructor, copy constructor, copy assignment operator, move constructor (because of copy elision, there is no overhead if the copy assignment operator takes its argument by value)
  • Destructor, copy constructor, copy assignment operator, move constructor, move assignment operator

Note that move constructor and move assignment operator won't be generated for a class that explicitly declares any of the other special member functions, that copy constructor and copy assignment operator won't be generated for a class that explicitly declares a move constructor or move assignment operator, and that a class with a explicitly declared destructor and implicitly defined copy constructor or implicitly defined copy assignment operator is considered deprecated. In particular, the following perfectly valid C++03 polymorphic base class

class C {
  virtual ~C() { }   // allow subtype polymorphism
};

should be rewritten as follows:

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};

A bit annoying, but probably better than the alternative (automatic generation of all special member functions).

In contrast to the Rule of the Big Three, where failing to adhere to the rule can cause serious damage, not explicitly declaring the move constructor and move assignment operator is generally fine but often suboptimal with respect to efficiency. As mentioned above, move constructor and move assignment operators are only generated if there is no explicitly declared copy constructor, copy assignment operator or destructor. This is not symmetric to the traditional C++03 behavior with respect to auto-generation of copy constructor and copy assignment operator, but is much safer. So the possibility to define move constructors and move assignment operators is very useful and creates new possibilities (purely movable classes), but classes that adhere to the C++03 Rule of the Big Three will still be fine.

For resource-managing classes you can define the copy constructor and copy assignment operator as deleted (which counts as definition) if the underlying resource cannot be copied. Often you still want move constructor and move assignment operator. Copy and move assignment operators will often be implemented using swap, as in C++03. If you have a move constructor and move assignment operator, specializing std::swap will become unimportant because the generic std::swap uses the move constructor and move assignment operator if available, and that should be fast enough.

Classes that are not meant for resource management (i.e., no non-empty destructor) or subtype polymorphism (i.e., no virtual destructor) should declare none of the five special member functions; they will all be auto-generated and behave correct and fast.

Is floating-point == ever OK?

30 votes

Just today I came across a third party software we're using and in their sample code there was something along these lines:

// defined in somewhere.h
static const double BAR = 3.14;

// code elsewhere.cpp
void foo(double d)
{
    if (d == BAR)
        ...
}

I'm aware of the problem with floating-points and their representation, but it made me wonder if there are cases where float == float would be fine?

Thanks in advance!

UPDATE: Thanks for the answer. Could you please give examples when it's fine?

UPDATE2: Actually one clarification. I'm not asking for when it COULD work but when it makes sense and works.

UPDATE3: What about:

foo(BAR);

will this always compare equal as they both use the same (do they?) static const BAR?

There are two ways to answer this question:

  1. Are there cases where float == float gives the correct result?
  2. Are there cases where float == float is acceptable coding?

The answer to (1) is: Yes, sometimes. But it's going to be fragile, which leads to the answer to (2): No. Don't do that. You're begging for bizarre bugs in the future.

EDIT: To address your third update: In that particular case the comparison will return true, but when you are writing foo you don't know (and shouldn't depend on) how it is called. For example, calling foo(BAR) will be fine but foo(BAR * 2.0 / 2.0) (or even maybe foo(BAR * 1.0) depending on how much the compiler optimises things away) will break. You shouldn't be relying on the caller not performing any arithmetic!

Long story short, even though a == b will work in some cases you really shouldn't rely on it. Even if you can guarantee the calling semantics today maybe you won't be able to guarantee them next week so save yourself some pain and don't use ==.

To my mind, float == float is never* OK because it's pretty much unmaintainable.

*For small values of never.

What does "class :" mean in C++?

29 votes

I've never seen it before. I thought it was a typo for "::sample", but when I saw it actually compiles, I was very confused. Can anyone help me find out please? I don't think it's a goto label...

void f() {
  class: sample {
    // there were some members declared here
  } x;
}

Thanks!

It is an unnamed class, and the colon means it inherits privately from sample. See it like

class Foo : private sample
{
    // ...
};

Foo x;

C++ standard library - when should I use it and when shouldn't I?

26 votes

Hello, I was wondering how often people actually use much of the standard c++ library, particularly the stuff in the <algorithm> and <numeric> headers. The text books seem to recommend them, but I haven't seen any of them used at all in various projects I've sifted through (coincidence?) and personally it seems easier to just write appropriate simple algorithms myself each time rather than memorize or consult a reference to these headers each time. Am just being lazy or stubborn? Is there actually performance gains etc when using these libraries?

Thanks,

R

It's possible you're being lazy or stubborn. Personally, I use them all the time in production code.

I don't do this to be fancy, and I don't do this because I like writing "space-age code." Rather, I do this because I am a paranoid programmer, and I know that production environments are hostile places that will mutilate code and reduce my programs to smoking piles of worthless bytes, if given a chance.

I do this because I live by the motto, "The best code, is the code you never write." It takes time to learn how to use the STL & Std Lib effectively, but once you do you'll find that it can be used so that what now is 1000 lines of code becomes perhaps 100. Those 100 might take as long to write as the original 1000, but there are fewer failure points. The code can be more robust, if you stand on the shoulders of others.

Undefined Behavior and Sequence Points Reloaded

22 votes

Consider this topic a sequel of the following topic:

Previous Installment
Undefined Behavior and Sequence Points

Let's revisit this funny and convoluted expression (the italicized phrases are taken from the above topic *smile* ):

i += ++i;

We say this invokes undefined-behavior. I presume that when say this, we implicitly assume that type of i is one of built-in types.

So my question is: what if the type of i is a user-defined type? Say it's type is Index which is defined later in this post (see below). Would it still invoke undefined-behavior?

If yes, why? Is it not equivalent to writing i.operator+=(i.operator++()); or even syntactically simpler i.add(i.inc());? Or, do they too invoke undefined-behavior?

If no, why not? After all, the object i gets modified twice between consecutive sequence points. Please recall the rule of thumb : an expression can modify an object's value only once between consecutive "sequence points. And if i += ++i is an expression, then it must invoke undefined-behavior. If so, then it's equivalents i.operator+=(i.operator++()); and i.add(i.inc()); must also invoke undefined-behavior which seems to be untrue! (as far as I understand)

Or, i += ++i is not an expression to begin with? If so, then what is it and what is the definition of expression?

If it's an expression, and at the same time, it's behavior is also well-defined, then it implies that the number of sequence points associated with an expression somehow depends on the type of operands involved in the expression. Am I correct (even partly)?


By the way, how about this expression?

//Consider two cases :
//1. if a is an array of built-in type
//2. if a is user-defined type which overloads subscript operator!

a[++i] = i; //taken from the previous topic. but here type of `i` is Index.

Must consider this too in your response (if you know it's behavior for sure). :-)


Is

++++++i;

well-defined in C++03? After all, this is this,

((i.operator++()).operator++()).operator++();

class Index
{
    int state;
public:
    Index(int s) : state(s) {}
    Index& operator++()
    {
        state++;
        return *this;
    }
    Index& operator+=(const Index & index)
    {
        state+= index.state;
        return *this;
    }
    operator int()
    {
        return state;
    }
    Index & add(const Index & index)
    {
        state += index.state;
        return *this;
    }
    Index & inc()
    {
        state++;
        return *this;
    }
};

It looks like the code

i.operator+=(i.operator ++());

Works perfectly fine with regards to sequence points. Section 1.9.17 of the C++ ISO standard says this about sequence points and function evaluation:

When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function.

This would indicate, for example, that the i.operator ++() as the parameter to operator += has a sequence point after its evaluation. In short, because overloaded operators are functions, the normal sequencing rules apply.

Great question, by the way! I really like how you're forcing me to understand all the nuances of a language that I already thought I knew (and thought that I thought that I knew). :-)

22 votes

This code is taken from a discussion going on here.

someInstance.Fun(++k).Gun(10).Sun(k).Tun();

Is this code well-defined? Is ++k in Fun() evaluated before k in Sun()?

What if k is user-defined type, not built-in type? And in what ways the above function calls order is different from this:

eat(++k);drink(10);sleep(k);

As far as I know, in both situations, there exists a sequence point after each function call. If so, then why can't the first case is also well-defined like the second one?

Section 1.9.17 of the C++ ISO standard says this about sequence points and function evaluation:

When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function.

This depends on how Sun is defined. The following is well-defined

struct A {
  A &Fun(int);
  A &Gun(int);
  A &Sun(int&);
  A &Tun();
};

void g() {
  A someInstance;
  int k = 0;
  someInstance.Fun(++k).Gun(10).Sun(k).Tun();
}

If you change the parameter type of Sun to int, it becomes undefined. Let's draw a tree of the version taking an int.

                     <eval body of Fun>
                             |
                             % // pre-call sequence point
                             | 
 { S(increment, k) }  <-  E(++x) 
                             |     
                      E(Fun(++k).Gun(10))
                             |
                      .------+-----.       .-- V(k)--%--<eval body of Sun>
                     /              \     /
                   E(Fun(++k).Gun(10).Sun(k))
                              |
                    .---------+---------. 
                   /                     \ 
                 E(Fun(++k).Gun(10).Sun(k).Tun())
                              |
                              % // full-expression sequence point

As can be seen, we have a read of k (designated by V(k)) and a side-effect on k (at the very top) that are not separated by a sequence point: In this expression, relative to each other sub-expression, there is no sequence point at all. The very bottom % signifies the full-expression sequence point.

What mutation-testing frameworks exist for C/C++?

21 votes

Mutation testing has been out there for a while now, and it seems there are at least one or two commercial mutation testing frameworks for C/C++. Have you used them? What are your experiences? Are there any open source alternatives?

A brief search resulted in:

With that said, you need to realize that mutation testing isn't particularly useful (at least from some stuff I've previously read). It's an interesting tool when faced with hard (metaphorically speaking) asserts and for making sure that data requirements are heeded to (when dealing with if and only if situations).

In my opinion, there are much more established ways of analyzing the robustness of code.

declaring a const instance of a class

19 votes

Let's say I have a class defined as follows:

class foo{};

now, this is perfectly acceptable;

foo f;

how come this is a compiler error? (uninitialized const ‘f’)

const foo f;

Why do we have to do this?

const foo f = foo();

I know why we can't do this..

const foo f(); // though it compiles..

Interestingly, the following is valid:

const std::string f;

So what is missing from foo?

I realize that there are three questions there and it's bad form, but I'm hoping someone can clear this up for me in one answer.

EDIT: please feel free to close it if it's stupid...

Your class is a POD (essentially because it doesn’t provide a default constructor). POD variables are not initialized upon declaration. That is, this:

foo x;

does not initialize x to a meaningful value. This has to be done separately. Now, when you declare it as const, this may never happen because you cannot assign to or change x any more.

Consider the equivalence to int:

int x; // legal
const int y; // illegal

As you have noticed, using std::string instead of foo compiles. That’s because std::string is not a POD. A simple solution to your dilemma is to provide a default constructor for foo:

class foo {
public:
    foo() { }
};

Now your const foo x; code compiles.

Why pre-increment operator gives rvalue in C ?

19 votes

In C++, pre-increment operator gives lvalue because incremented object itself is returned, not a copy. But in C, it gives rvalue. Why?

C doesn't have references. In C++ ++i returns a reference to i (lvalue) whereas in C it returns a copy(incremented).

C99 6.5.3.1/2

The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation. The expression ++Eis equivalent to (E+=1).

‘‘value of an expression’’ <=> rvalue

However for historical reasons I think "references not being part of C" could be a possible reason.

Why does the "static" keyword have so many meanings in C and C++?

18 votes

As we know, the keyword static has multiple meanings in C. C99 added the possibility of legally writing

void foo (int arr[static 50])
{
    // ...
}

which adds to the confusion, and C++ has static member variables and functions.

This would not be so troublesome if all the uses could be connected in some way, but I find it hard to find that link for some of the cases. Particularly why the static keyword should be used to modify visibility (linkage), or what on earth it's got to do with an array's minimum amount of elements.

So is there a historical reason for the abuse of the static keyword, or is there a secret link under the hood that connects all of its uses?

Adding new keywords to a language breaks backwards compatibility. So static gets used where its use might possibly mean something ( int arr[static 50] vs int arr[auto 50] or int arr[extern 50] ) and cannot syntactically appear in that location based its use in previous versions.

Though in that case adding a not_less_than context sensitive keyword in that position would not break previous code, it would add another keyword (so simple text editors which are keyword aware but not syntax aware would not know whether or not it is a keyword), and break the 'keywords are not context sensitive' simplification made in C.

How to stop time from running backwards on Linux?

18 votes

Here's a little test I've written to verify that time does indeed only run forwards in Linux.

#include <time.h>
#include <sys/time.h>  

bool timeGoesForwardTest2()
{
   timeval tv1, tv2;   
   double startTime = getTimeSeconds();  // my function

   while ( getTimeSeconds() - startTime < 5 )
   {
      gettimeofday( &tv1, NULL );  
      gettimeofday( &tv2, NULL );  

      if ( tv2.tv_usec == tv1.tv_usec &&
           tv2.tv_sec == tv1.tv_sec )
      {
         continue;  // Equal times are allowed.
      }

      // tv2 should be greater than tv1
      if ( !( tv2.tv_usec>tv1.tv_usec ||
              tv2.tv_sec-1 == tv1.tv_sec ) )
      {
         printf( "tv1: %d %d\n", int( tv1.tv_sec ), int( tv1.tv_usec ) );
         printf( "tv2: %d %d\n", int( tv2.tv_sec ), int( tv2.tv_usec ) );
         return false;
      }         
   }
   return true;
}

Test fails with the result.

 tv1: 1296011067 632550
 tv2: 1296011067 632549

ummm....

Why does this happen?

Here's my setup:

Linux version 2.6.35-22-generic (buildd@rothera) (gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu4) ) #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 (Ubuntu 2.6.35-22.33-generic 2.6.35.4)
... running inside VirtualBox 3.2.12, in Windows 7.

There is an open issue at the VirtualBox Bug Tracker. They link to a blog post stating why you shouldn't use gettimeofday() to measure the passage of time:

The most portable way to measure time correctly seems to be clock_gettime(CLOCK_MONOTONIC, ...)

Is it safe to bind a reference to a not yet constructed object in C++?

18 votes

Consider this code sample:

class Base {
public:
    Base( string& _object ) : object( _object ) {}
private:
    string& object;
};

class Derived: public Base {
public:
    Derived() : Base( object ) {}
private:
   string object;
};

Obviously first Base is constructed and it is passed a reference to a not yet constructed object.

Memory is allocated for the whole Derived object, so Derived::object is in legally accessible memory, just its constructor has not run. Base::Base() doesn't call any methods of passed object, only stores the reference. It works in Visual C++ 9.

Is it safe according to C++ Standard?

It is safe, as long as you don't "use" the reference before object is constructed. You can use the base-from-member idiom to move object into a (private) base class which comes before Base, and thus be constructed before Base, if you need to change the construction order:

struct Base {
  Base(string &ref) {
    cout << "imagine the ctor uses the ref: " << ref;
  }
};

struct DerivedDetail {
  DerivedDetail(string const &x) : object (x) {}
  string object;
};

struct Derived : private DerivedDetail, Base {
  Derived() : DerivedDetail("foobar"), Base(object) {}
  // In particular, note you can still use this->object and just
  // ignore that it is from a base, yet this->object is still private
  // within Derived.
};

C++03 §3.8p6:

…before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any lvalue which refers to the original object may be used but only in limited ways. Such an lvalue refers to allocated storage (3.7.3.2), and using the properties of the lvalue which do not depend on its value is well-defined. …

In a nutshell: don't access any members, methods, or pass it to anything that does. You can take its address and bind references to it.

Is memory allocation in linux non-blocking?

15 votes

I am curious to know if the allocating memory using a default new operator is a non-blocking operation.

e.g.

struct Node {
    int a,b;
};

...

Node foo = new Node();

If multiple threads tried to create a new Node and if one of them was suspended by the OS in the middle of allocation, would it block other threads from making progress?

The reason why I ask is because I had a concurrent data structure that created new nodes. I then modified the algorithm to recycle the nodes. The throughput performance of the two algorithms was virtually identical on a 24 core machine. However, I then created an interference program that ran on all the system cores in order to create as much OS pre-emption as possible. The throughput performance of the algorithm that created new nodes decreased by a factor of 5 relative the the algorithm that recycled nodes.

I'm curious to know why this would occur.

Thanks.

*Edit : pointing me to the code for the c++ memory allocator for linux would be helpful as well. I tried looking before posting this question, but had trouble finding it.

seems to me if your interference app were using new/delete (malloc/free), then the interference app's would interfere with the non recycle test more. But I don't know how your interference test is implemented.

Depending on how you recycle (ie if you use pthread mutexes god forbid) your recycle code could be slow (gcc atomic ops would be 40x faster at implementing recycle).

Malloc, in some variation for a long time on at least some platforms, has been aware of threads. Use the compiler switches on gcc to be sure you get it. Newer algorithms maintain pools of small memory chunks for each thread, so there is no or little blocking if your thread has the small item available. I have over simplified this and it depends on what malloc your system is using. Plus, if you go and allocate millions of items to do a test....well then you wont see that effect, because the small item pools are limited in size. Or maybe you will. I don't know. If you freed the item right after allocating, you would be more likely to see it. Freed small items go back into the small item lists rather than the shared heap. Although "what happens when thread B frees an item allocated by thread A" is a problem that may or may not be dealt with on your version of malloc and may not be dealt with in a non blocking manner. For sure, if you didn't immediately free during a large test, then the the thread would have to refill its small item list many times. That can block if more than one thread tries. Finally, at some point your process' heap will ask the system for heap memory, which can obviously block.

So are you using small memory items? For your malloc I don't know what small would be, but if you are < 1k that is for sure small. Are you allocating and freeing one after the other, or allocating thousands of nodes and then freeing thousands of nodes? Was your interference app allocating? All of these things will affect the results.

How to recycle with atomic ops (CAS = compare and swap):

First add a pNextFreeNode to your node object. I used void*, you can use your type. This code is for 32 bit pointers, but works for 64 bit as well. Then make a global recycle pile.

void *_pRecycleHead; // global head of recycle list. 

Add to recycle pile:

void *Old;
while (1) { // concurrency loop
  Old = _pRecycleHead;  // copy the state of the world. We operate on the copy
  pFreedNode->pNextFreeNode = Old; // chain the new node to the current head of recycled items
  if (CAS(&_pRecycleHead, Old, pFreedNode))  // switch head of recycled items to new node
    break; // success
}

remove from pile:

void *Old;
while (Old = _pRecycleHead) { // concurrency loop, only look for recycled items if the head aint null
  if (CAS(&_pRecycleHead, Old, Old->pNextFreeNode))  // switch head to head->next.
    break; // success
}
pNodeYoucanUseNow = Old;

Using CAS means the operation will succeed only if the item you are changing is the Old value you pass in. If there is a race and another thread got there first, then the old value will be different. In real life this race happens very very rarely. CAS is only slighlty slower than actually setting a value so compared to mutexes....it rocks.

The remove from pile, above, has a race condition if you add and remove the same item rapidly. We solve that by adding a version # to the CAS'able data. If you do the version # at the same time as the pointer to the head of the recycle pile you win. Use a union. Costs nothing extra to CAS 64 bits.

union TRecycle {
  struct {
    int iVersion;
    void *pRecycleHead;
  } ;  // we can set these.  Note, i didn't name this struct.  You may have to if you want ANSI
  unsigned long long n64;  // we cas this
}

Note, You will have to go to 128 bit struct for 64 bit OS. so the global recycle pile looks like this now:

TRecycle _RecycleHead;

Add to recycle pile:

while (1) { // concurrency loop
  TRecycle New,Old;
  Old.n64 = _RecycleHead.n64;  // copy state
  New.n64 = Old.n64;  // new state starts as a copy
  pFreedNode->pNextFreeNode = Old.pRecycleHead;  // link item to be recycled into recycle pile
  New.pRecycleHead = pFreedNode;  // make the new state
  New.iVersion++;  // adding item to list increments the version.
  if (CAS(&_RecycleHead.n64, Old.n64, New.n64))  // now if version changed...we fail
    break; // success
}

remove from pile:

while (1) { // concurrency loop
  TRecycle New,Old;
  Old.n64 = _RecycleHead.n64;  // copy state
  New.n64 = Old.n64;  // new state starts as a copy
  New.pRecycleHead = New.pRecycledHead.pNextFreeNode;  // new will skip over first item in recycle list so we can have that item.
  New.iVersion++;  // taking an item off the list increments the version.
  if (CAS(&_RecycleHead.n64, Old.n64, New.n64))  // we fail if version is different.
    break; // success
}
pNodeYouCanUseNow = Old.pRecycledHead;

I bet if you recycle this way you will see a perf increase.

How will _exit behave in a C++ program?

12 votes

C99 offers the _Exit function, which exits "immediately", although it does may close file descriptors. Unix/POSIX extends this behavior by mandating the closing of all fd's without flushing (and offers the synonym _exit).

Will these functions call destructors for static objects when called from a C++ program? Does the C++ standard make any guarantees about _Exit?

(Inspired by this question; I suddenly wondered what happens in the typical fork-exec-_exit idiom in C++.)

It simply doesn't exist in standard C++, so there are no guarantees.

It is planned for inclusion in C++0x. That specifies (§18.5):

The function _Exit(int status) has additional behavior in this International Standard:

— The program is terminated without executing destructors for objects of automatic, thread, or static storage duration and without calling functions passed to atexit() (3.6.3).

Write the prototype for a C function that takes an array of exactly 16 integers

11 votes

One of the interview questions asked me to "write the prototype for a C function that takes an array of exactly 16 integers" and I was wondering what it could be? Maybe a function declaration like this:

void foo(int a[], int len);

Or something else?

And what about if the language was C++ instead?

In C, this requires a pointer to an array of 16 integers:

void special_case(int (*array)[16]);

It would be called with:

int array[16];
special_case(&array);

In C++, you can use a reference to an array, too, as shown in Nawaz's answer. (The question asks for C in the title, and originally only mentioned C++ in the tags.)


Any version that uses some variant of:

void alternative(int array[16]);

ends up being equivalent to:

void alternative(int *array);

which will accept any size of array, in practice.


The question is asked - does special_case() really prevent a different size of array from being passed. The answer is 'Yes'.

void special_case(int (*array)[16]);

void anon(void)
{

    int array16[16];
    int array18[18];
    special_case(&array16);
    special_case(&array18);
}

The compiler (GCC 4.5.2 on MacOS X 10.6.6, as it happens) complains (warns):

$ gcc -c xx.c
xx.c: In function ‘anon’:
xx.c:9:5: warning: passing argument 1 of ‘special_case’ from incompatible pointer type
xx.c:1:6: note: expected ‘int (*)[16]’ but argument is of type ‘int (*)[18]’
$

Change to GCC 4.2.1 - as provided by Apple - and the warning is:

$ /usr/bin/gcc -c xx.c
xx.c: In function ‘anon’:
xx.c:9: warning: passing argument 1 of ‘special_case’ from incompatible pointer type
$

The warning in 4.5.2 is better, but the substance is the same.