Archive

Archive for the ‘Learning’ Category

Cast away

My C++ class is done, and I feel like I learned some tiny things here and there, mostly refresher stuff, but not a lot of meat to sink my teeth into.

So, to learn more, I turned to Stack Overflow, and while wanting to be helpful, got served. It’s alright, it’s cool, I learned I had still lots to learn. And that’s why I will talk about casting.

Usually, in a function, you should get your types right, and avoid wasteful casting. That’s true. Compilers throw warnings at you if you don’t respect types, and that’s usually where you need to be explicit about what you mean. C has the classic cast, what most call the C-style cast:

    int i = 35;
    float f = (float)i;

C++ offers a lot more tools. Most of the time, we’re casting to another type to adapt to a situation, a function, etc. C++ allows us to be more explicit, which is good, because you’re making your meaning clear to future maintainers of your code (and that can be yourself). Never neglect the power of explicit code. Don’t just cast to make it work (or not send a warning), cast and be clear about your intentions.

These are called casting operators, and they go as follows.

First, const_cast.

const_cast exists to deal with whether a variable or parameter is constant or not. Sometimes, you need to get rid of “const” for just a bit. Casting it C-style works, but the C++ way is crystal:

void nonconstfunc(int *i);

void constfunc(const int *i)
{
    nonconstfunc(i); //error, this will not compile
    int* i2 = const_cast<int*>(i); // but convert it to a non-const int pointer
    nonconstfunc(i2); //and use the non-const copy instead!
}

Next is reinterpret_cast.

reinterpret_cast does a very specific job: it can cast a pointer to an integral type and back. So if you have a pointer and you want to print its address, say, you can use this:

int main(int argc, char *argv[])
{
	long adr = reinterpret_cast<long>(argv);
	cout << adr;
	return 0;
}

It’s a very specific use. Changing the value and casting it back to pointer is definitely not recommended. You can see this being used to hash an address and put it in a hash table, for example.

The next two are opposite sides of the same coin: dynamic_cast and static_cast. I don’t fully grok them yet, so I will not elaborate on them in this post. Suffice it to say that they complement each other. dynamic_cast runs real-time checks, while static_cast does not, which makes it faster. Both can cast up or down a chain of inheritance. So I will grok and get back to this.

Advertisements
Categories: Learning Tags:

C/C++ inline keyword

2012-02-12 2 comments

It’s always been fuzzy in my mind what inline does. An ex-colleague who had discovered it said it was to make things faster, but I was certain it wasn’t just a magic word. Now it’s a bit clearer.

Suppose you have a very simple function:

int add(int a, int b)
{
    return a + b;
}

That’s not very processing intensive, right? But when this is compiled, what happens? Well, it’s a function, and a function has a place in memory. When the function is called in execution, the context is changed to reach that “add” function, execute it, and return the result (my simplification of the wording betrays my lack of knowledge of assembly, I know). So that’s basically three operations for a simple addition. One way to speed that up is to tell the compiler to make this function inline, that is to say, to not leave the context for when it is called. In other words, the function’s code replaces each call.

inline int add(int a, int b)
{
    return a + b;
}

It keeps the logic nice and tidy, but at the same time speeds up execution. There is a downside, however: the program will have a larger memory footprint. That means it could, in the end, slow down execution (if there are many inline functions).

One nice way to use this is for C++ accessors:

// myclass.h
class MyClass
{
private:
    int m_int;
public:
    int GetInt() const;
    void SetInt(int);
}

inline int MyClass::GetInt() const
{
    return m_int;
}
inline void MyClass::SetInt(int value)
{
    m_int = value;
}

Put the inline functions in your header file, and you’re all set.

Categories: Learning Tags: ,

Initialization lists in C++

New thing learned! This is actually a really nice one.

Suppose a class with three properties:

class MyClass
{
public:
    MyClass(int property1, char property2, float property3);
private:
    int m_property1;
    char m_property2;
    float m_property3;
}

A constructor that’s essentially trivial (no validation) would look like this:

MyClass::MyClass(int property1, char property2, float property3)
{
    m_property1 = property1;
    m_property2 = property2;
    m_property3 = property3;
}

There is, however, a more concise way to write this with something called an initializer list:

MyClass::MyClass(int property1, char property2, float property3)
: m_property1(property1), m_property2(property2), m_property3(property3)
{
}

Much cleaner. If some elements require validation, they don’t need to be in the list.

There’s a whole lot more here: http://www.cprogramming.com/tutorial/initialization-lists-c++.html

UPDATE (2012-02-09):

For this course I’m taking, I’m using GCC to compile. One of the differences I found with Visual Studio’s compiler is that with GCC requires that the elements initialized be listed in the same order as properties (in the class’ private section) and in the constructor.

UPDATE (2012-03-26)

One thing I had not caught on originally is beyond the syntax. Yes, it’s a clean syntax, but the main feature is that there is no pre-assignment. In C++, at the start of the constructor (in laymen’s terms, right after the opening bracket), all class attributes are assigned. What you’re doing with this:

m_property1 = property1;

is basically the second assignment of m_property1, the first being its default. If it’s a simple type, there’s no harm done, but if it’s an object of a class, that means the default constructor was called. Worst, if it’s a class you wrote, it means you have to give it a default constructor. If your class doesn’t naturally need a default constructor, this is bad. The extra instantiation alone, the hidden one, is bad, you’re wasting valuable resources. In an initialization list, the property is assigned directly. Waste not, want not.

Categories: Learning Tags:

typedef and structs

Another thing I learned in the C introduction to “Advanced C++ Programming”, typedef used with structs. Every teacher (and everyone else) I asked before kept saying typedef was “sorta complicated”, which meant they either didn’t know or didn’t want to explain it to me.

As I understand it, typedef is an instruction which tells the compiler to treat what is defined as a type.

For example, given a defined structure:

struct MyStruct
{
    int var1;
    char var2;
};

Using this struct means carrying the struct keyword everywhere.

//Anywhere it is declared
struct MyStruct my;
//And in function parameters too
void MyFunc(struct MyStruct my);

typedef simplifies this greatly:

typedef struct
{
    int var1;
    char var2;
} MyStruct;

//Declaration
MyStruct my;
//Parameter declaration
void MyFunc(MyStruct my);
Categories: Learning Tags:

C blocks and variable declaration

First thing I learned in the “I’m supposed to know this already!” class (Advanced C++ Programming) is actually about C.

In C++ variables can be declared anywhere in the scope of a function (well, anywhere before they’re used). In C, however, they have to be declared at the beginning of the function. Or so I thought. It’s actually at the top of the block. And a block is delimited by curly braces.

In other words, declaring at the top of a function:

void MyFunction(void)
{
    int myVar;
    //...
}

Inside a control structure:

void MyFunction(void)
{
    if(/*some condition*/)
    {
        int myVar;
        //...
    }
}

or

void MyFunction(void)
{
    for(/*start, end, iteration*/)
    {
        int myVar;
        //...
    }
}

or even

void MyFunction(void)
{
    switch (/*expression*/)
    {
        case 1:
        {
            int myVar;
            //...
        }
    }
}

And even just out of the blue:

void MyFunction(void)
{
    //some code
    {
        int myVar;
        //...
    }
}

Although this last form should arguably be used sparingly. And here I thought I had to list it all at the very beginning of the function. I’m ashamed, but I’m glad I know now.

Add-on: I forgot to mention the scope. The variable exists in the block. It’s a local declaration only valid in it. Outside the block, the variable no longer exists. Your compiler will tell you if you refer to a variable declared in a block outside of it.

Categories: Learning Tags:

Look at me, I’m learning!

Time to dust off this place and bring it back to life!

I have a course this semester, called Advanced C++ Programming. It’s mandatory, and I know most of what’s being taught. I still enjoy it, the prof. is no-nonsense, and drops bombs like:

If a code base cannot be maintained, it might as well just not work.

which resonates strongly with what I’m working with. So there’s a lot of focus on code clarity and re-usability. I’m loving that discourse.

At the same time, I do learn some tiny bits here and there, and for as long as it’s manageable, I will post them here.

Categories: Learning