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.

Wednesday, December 16, 2015

Remove a single character from std::string

This  might probably be one of the oldest tricks for 2015 for std::string but still blogging about it anyways.

To remove all instances of a single character from a std::string, you can use std::remove and string::erase.

#include // include for remove()

std::string str = "This is a test";
str.erase( std::remove( str.begin(), str.end(), 'e' ), str.end() );

This would remove the character e from string, and will provide result of "This is a tst"

If you want to remove quotes from the string,

std::string str = "This \" is a test \"";
str.erase( std::remove( str.begin(), str.end(), '\"' ), str.end() );

result str will have "This is a test" without the quotes. 

Thursday, December 10, 2015

C++ and aggregate initialization

There is an easier way to initialize a char array with all 0s instead of using the traditional memset

So this code

char array1[1024];
memset(array1, 0, sizeof(array1));

can be replaced with

char array[1024] = {0};
char array[1024] = {}; //same as {0}

Which is basically the same but on a single line implementation.

Section 8.5.1 of the ISO Spec states

"An aggregate is an array or a class with  no user declared constructors, no private or protected non static data members, no base classes, and no virtual functions"

If you want to initialize such an aggregate you can use {}.

This is not only  used to set everything to 0, but to also initialize class members.

For e.g.

struct ExampleStruct
{
   int x;
   int y;
   int z;
};

If you have a simple struct like this with no constructors, all public members, then you can initialize its members in a single line like this

ExampleStruct Object = { 2, 3, 6 };

Which would set x = 2, y = 3 and z = 6.

Also as per C++11, = {0} is required to set the padding bytes to 0 by the standards. For e.g

struct ExampleStruct
{
   char x;
   int y;
}

ExampleStruct Object = {0}
will set x = 0 and y = 0 , and the padded bytes between x and y will be 0.



Thursday, November 26, 2015

Hosting webserver on Mac with Python

I needed to host a webserver with basic setup to load a file for a project. Here is what I did

1. in Mac, I opened terminal, and went to the folder that had index.html and typed
python -m SimpleHTTPServer 8000
This spit out the following log
Serving HTTP on 0.0.0.0 port 8000 ...
And it hung there. Which is indication that the server is running on port 8000

That is all that you would have to do to host a webserver on Mac with python.

In order to access this file from a different system, we need the name or ip address for localhost.
ip address can be obtained by typing ifconfig in terminal, and getting the inet address of en0 section, if you are connected to the internet via ethernet LAN cable.

Or you can go to system preferences -> Network and get the ip address given in the right side section of the preference window in Mac

After getting the ip address, if you type http://xxx.yyy.zzz.uuu:8000/index.html, it should display the webpage.


Hope this helps. 

Thursday, November 19, 2015

CPPCheck and latest 1.71 version


I normally use CPPCheck to verify the code sanity in my c++ projects. Few days back I tried to update to latest from 1.69 version. I uninstalled 1.69, and installed latest 1.71 from http://cppcheck.sourceforge.net. But when attempting to run the application, it says MSVCP140.dll missing.

Here is how I fixed it, and thought this blog post might help others who also have similar issue.
This dll belongs to MS Visual C++ as the name in the dll suggests. Downloading Visual C++ redistributable for Visual Studio 2015, even though you dont use 2015 version, should fix this missing dll issue. It can be downloaded and installed from https://www.microsoft.com/en-us/download/confirmation.aspx?id=48145


Hope this helps.