Friday, February 23, 2007

C++ - Forward Declarations

If a class declaration (in a header file) does not need to know the size of any included classes/structs (i.e., the class declaration does not need to contain an actual instantiation of another class or access member data or functions of another class), forward declare the dependent classes/structs to minimize dependencies.

In other words, use pointers and references of classes/structs with respective forward declarations instead of member objects instantiations and #include's. Then, #include dependent files to access the other classes' members and functions in the source file (.c,.cpp). Remember to delete the pointers in the destructor if the class owns the pointer.

In myClass.h:
//Forward declarations
class OtherClass; // defined in otherClass.h
struct OtherStruct; // defined in otherStruct.h

class MyClass
{
private:
OtherClass *mMyOtherClass; //pointer
OtherStruct &mMyOtherStruct; //reference
public:
MyClass(OtherStruct &_struct);
~MyClass();
};

In myClass.cpp
#include "myClass.h"
// include headers of forward declarations
#include "otherClass.h"
#include "otherStruct.h"

MyClass::MyClass(OtherStruct &_struct)
: mMyOtherClass(new MyOtherClass),
// references can only be initialized in
// constructor initialization list
mMyOtherStruct(_struct)
{
// Empty constructor body
}

MyClass::~MyClass()
{
delete mMyOtherClass;
}

C++ - Minimize Dependencies

A change in a header file (.h, .hpp) causes every other header file that includes it to be recompiled. Thus, to decrease incremental build times, strive to minimize the number of #include's in header files.

Note this cannot be done with every header file, such as files containing dependencies on template classes or typedefs.

C++ - const Keyword

Use the keyword const to signify (to developers, not just the compiler) that a variable does not change).

/**
* This method doesn't change its object
* @param[in] obj Reference to a constant MyObj
* @return A constant reference to obj
*/
const MyObj& MyObj::myMethod(const MyObj &obj) const
{
return obj;
}

C++ - Parameter Passing

Avoid passing large objects by value. This causes unnecessary copying of those objects on to the stack, slowing down performance. Instead, pass by reference (or pointer).

When needed, use prefixes "in" and "out" to avoid confusion with outgoing parameters.

Pass by value (NG=No Good):
void func(BigObject obj) // Use copy of obj
{
...
}

Pass by reference (Good):
void func(BigObject &obj) // Uses reference of obj
{
...
}

Note that smaller primitives (e.g. int, short, char) do not benefit from passing by reference because most the time, they are either equal to or smaller than the word size of the machine.

C++ - Initialization Lists

Constructing an object consists of two parts:
  1. Creating the object
    • Without initialization list: Assign default values to the object's member variables
    • With initialization list: Assign specified values in initialization list to member variables
  2. Running the constructor's body
In object creation without an initialization list, default values are assigned to the object's member data. If assignments exist inside the body of the constructor, member data will be assigned again. However, with an initialization list, specified values can be assigned in step 1 to avoid assignments in the constructor's body.

Warning: there is no guarantee on the order of assignments (see example).

Before:
MyClass::MyClass()
{
member1 = 1;
member2 = 2;
member3 = member2;
}

After:
MyClass::MyClass()
: member1(1),
member2(2)
//, member3(member2) // No guarantee member2
// was set before here
{
member3 = member2; // need to assign here
}

VIM - Advanced Tips

Here are some advanced tips I've learned from coworkers and working with VIM:

CommandDescription
:%s *$==Delete end of line spaces
:'a,'bs/str1/str2/gReplace "str1" with "str2" from marker a to marker b
:%s/\(.*\):\(.*\)/\2:\1/gReplace the first field (\1) with the second field (\2) separated by the :
zfFold a selected block of code
zdUnfold a block of folded code
:makeRun Makefile
:w|makeWrite (save) current file and then run Makefile
:grep regexp filesFind regexp in files
:copenOpen quickfix list. Helpful after doing :make or :grep. Press Enter on entry in quickfix list to jump to that location
:ccloseClose quickfix list
:colderDisplay contents of previous quickfix list
:cnewerDisplay contents of next quickfix list
:!cmdRun cmd as if on command line. Example: :!ls
:bwClose current buffer
ctrl+oGo back once through visited lines
ctrl+iGo forward once through visited lines
:h topicGet help for topic

Wednesday, February 21, 2007

GreatNews

I've tried many RSS aggregators but the one I like most is GreatNews from Curio Studio.

Here are some tips I've learned from using it for a while:
  • Ctrl+R: Mark feed as read
  • Ctrl+T: Create new tab
  • Middle click
    • Feeds: Opens originating page
    • Posts: Opens post in current tab
    • Links in posts: Opens link in new background tab
    • Tabs: Closes the tab
  • Tools → Options → Reading
    • Check "Mark previous feed as read when switching feeds"
  • Do not sort by date (or anything for that matter). This really slows it down.
  • Tools → Cleanup... : Cleans up unread posts

Friday, February 16, 2007

Web - Firefox Extensions

I can't imagine using Firefox without these essential extensions. You can download Firefox on the side bar.
Non-essential:

Thursday, February 15, 2007

Linux - Reinstalled Kubuntu

A few days ago, I wanted to install the new subversion client for Kubuntu because the old one didn't have the 'svn diff -c' option. I guess I shouldn't have because it depends on a newer cpp package, which the system depends on it. So after installing the new cpp package, my thesis wouldn't compile. I tried installing the old cpp but it kept using the new one. So last night I reinstalled Kubuntu. I updated all the packages and everything looks good. Hopefully, I will be able to work on my thesis tonight.