Saturday, January 30, 2016

C++11 and initializer list

This post is about one example of using initializer list in C++.

Imagine a parent child relationship between two classes.
Parent has a child (obviously).
Child has a pointer back to the parent.
Now the Child is not a pointer in the parent class, but a member object.

Here a simple and easy way to use initializer list in order to pass parents' "this" pointer to the constructor of the Child class

Class Child
{
private:
Parent* p;

public:
Child(Parent* p1): p(p1){}
};


Class Parent
{
private:
Child c;

public:
Parent(): c(this){}
};

This is perfectly fine. One can use "this" pointer inside the initalizer list or constructor as long as the object to which "this" pointer has been passed on to (i.e the child object), does not use the uninitialized members or virtual functions of the parent class.

For e.g Child class's constructor should not use any uninitialized pointers or members of parent class. Child class' constructor should not call any virtual function as well because one might expect the child class's virtual function definition to  be invoked. But it would in fact invoke the parent class's virtual function definition if any because the child class's virtual function will not be visible inside the child class's constructor.

Hence, uninitialized members are not yet initialized, and virtual functions would result in calling the base class function instead of derived class function.

Wednesday, January 27, 2016

find_if with const_iterator

This is somewhat old topic, but I am blogging it anyways.

In C++ if you want to use find() or find_if algorithms with const_iterator instead of iterator, for e.g inside a const member function that does not alter the member contents, and if you encounter any compiler complaints regarding the same, then

confirm that the return type is also a const_iterator and not an iterator. find() and find_if are written to take iterator and const_iterator into consideration and return the results as per the STL Algorithm docs. Hence if the code also is written to work with respective iterators compiler error would be taken care of.

for e.g
uint64_t ID = 34; //sample
std::vector::const_iterator itr = std::find_if(list.begin(), list.end(), [ID](const ListType& a){ return a.ID == ID; }); //lamdba function to find the object with ID.



Monday, January 25, 2016

Lifetime of Reference to vector element in C++

This post is about using const or non const reference to an object, and its lifetime upon the object's destruction. Especially when that object is a vector element.

This is an example source code:

std::vector& CarList; //global or a member in Carz class
void Carz::DoSomethingWithTheVector(){
  if(CarList.size() > 0)
  {
    const  Car& cref = CarList[0]; // Code #1
    MarketCar(cref); //deletes CarList[0] if car gets sold.
    AddCarToSoldList(cref); //Code #3
  }
  else
  {
    //Consider all cars as sold.
   //Calculate Sale amount
  }
}

void Carz::MarketCar(const Car& c)
{
  //market car
  if(c.sold())
  {
    //remove car from the list. 
    CarList.erase(CarList.begin()); // oops.  Code #2
  }
}

In the example above, since the reference points to the first element in the CarList, if the
1. First element gets deleted or
2. The List is sorted or rearranged in any way

and the reference is used after that,
the reference will not refer to the deleted memory.

It would indeed refer to the first element in the vector, which could be the second element after the first element gets deleted, or invalid memory if the vector became empty in MarketCar.

Though the reference is a const reference, that does not copy the first element and create a temporary memory. It is still a reference. Always pointing to the first element of the array.

Hence in the above code, the memory pointed to by cref, which is sent as parameter to AddCarToSoldList() will not be the first element of the array, but the second one, or invalid memory if vector is empty.

If any element is emplaced to the front of the vector, the cref would still point to first element of the list, now the newly added element.

Reference cref does not point to the deleted memory of the first element of the vector. Just rephrasing above point.

This might be a well known issue, that everyone knows but might have forgotten. Hoping this might help developers to follow the memory trace carefully. Hence blogging about it anyways.