May 2007 Archives

2007-05-14

Reading C type declarations

If you are interested, in what exactly char *(*(**foo[][8])())[]; declares go on an read this.

Yes, this is no C++ but a C topic. But as ISO C++ is (almost) a superset of C89 this nevertheless matters. Furhtermore it's fun. And a good example on how a language should not be defined.


Posted by Alexander Bernauer | Permanent Link | Categories: C++

2007-05-14

Weltanschauungen

Die gefährlichste Weltanschauung ist die Weltanschauung derjenigen, die die Welt nicht angeschaut haben.
Alexander von Humboldt

Posted by Alexander Bernauer | Permanent Link | Categories: Zitate

2007-05-12

Illuminate

A friend of mine just told me that he too hit the vector trap of my previous post. Instead of reading the STL code he wrote a class with debug output to track down what happens to the objects inside of the several containers.

Yeah! The illumination class. This is what everybody hacks at least once in his C++ live. And here goes mine:

class Illuminate {
public:
    Illuminate() : _id(id++)
    {
        cout << "default constructor " << _id << endl;
    }

    Illuminate(const Illuminate& rhs)
        : _id(id++)
    {
        cout << "copy constructor " << _id << " <- " << rhs._id <<  endl;
    }

    Illuminate& operator=(const Illuminate& rhs)
    {
        cout << "operator=" << _id << " <- " << rhs._id <<  endl;
        return *this;
    }

    ~Illuminate()
    {
        cout << "destructor " << _id << endl;
    }

private:
    static int id;
    const int _id;
};

int Illuminate::id = 0;

Use it for example like this:

int main()
{
    vector<Illuminate> foo(3);
    cout << "mark" << endl;
}
The program output then shows clearly what I tried to explain in my previous post:
default constructor 0
copy consstructor 1 <- 0
copy consstructor 2 <- 0
copy consstructor 3 <- 0
destructor 0
mark
destructor 1
destructor 2
destructor 3

Posted by Alexander Bernauer | Permanent Link | Categories: C++

2007-05-12

STL Fuckup

Today I have two things to say:

First beware of SGI's Standard Template Library Programmer's Guide. Although it is the STL docu out there it is not standard compliant!

For example it claims there is a vector(size_type n) and a vector(size_type n, const T& t) constructor for the vector class. This is not true. Section 23.2.4 of the ISO-C++ standard defines explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());.

You could argue that they just split the two cases into to different constructors. But apart from the missing default value for the second argument and the completely missing third argument this is not true. SGI explains:

  • vector(size_type n): Creates a vector with n elements.
  • vector(size_type n, const T& t): Creates a vector with n copies of t.
For me this means that the first constructor creates n objects by using the default construtor of the particular type. Especially because the documentation on Sequences, which is a model of vector, calls it a "Default fill constructor". In contrast to the first constructor the second one fills the vector by copying the given object.

And this leads to today's second point: there is no constructor to let the vector be filled with n objects each constructed by the default constructor. Instead the objects in the vector are always copies of the given one - which is discarded afterwards, by the way. This is a problem as soon as it matters, whether the objects are copied or not.

For instance imagine some struct Foo with a smart pointer of some type Bar being a member. The Foo constructor creates a new Bar object with operator new and passes the pointer to the smart pointer's constructor. What you want if you arrange such Foo objects within a vector normaly are n different Foo objects. But what you get are n Foo objects whose smart pointers all encapsulate the same Bar object. This is because the Foo constructor runs only once. The rest is done by the copy constructor.

I see no efficient way to get the vectory filled with n independent Foo objects. The best way I can see is like this:

vector<Foo> v;
v.reserve(n);
for (unsigend i=0; i<n; i++) {
    v.push_back(Foo());
}
Anyone a better idea? If yes send me an email. I'm eager to knonw whether I miss something.

Posted by Alexander Bernauer | Permanent Link | Categories: C++

2007-05-09

Memory Layout for Multiple and Virtual Inheritance

I recommend this article about the memory layout of C++ objects.

Posted by Alexander Bernauer | Permanent Link | Categories: C++

2007-05-09

Barriers

In addition to my post about why it is a problem that the compiler does not know anything about threads I recommend this article about memory barriers and multi core machines.

And please help him find pi :-)


Posted by Alexander Bernauer | Permanent Link | Categories: C++