Showing posts with label cpp. Show all posts
Showing posts with label cpp. Show all posts

Friday, February 19, 2016

C++ : auto_ptr

NOTE: auto_ptr is deprecated. Use std::unique_ptr instead !

auto_ptr is a smart pointer facility.
Usually, this is what we do when we manipulate pointers :

void f()
{
   T* pt( new T );
   /*...more code...*/
   delete pt;
}

With auto_ptr, no need to delete the object anymore, it is all  taken care of !

    void f()
    {
      auto_ptr<T> pt( new T );
      /*...more code...*/
    } // cool: pt's destructor is called as it goes out
      // of scope, and the object is deleted automatically

It ensures more robust code as we avoid potential memory leaks.

Ownership


Passing


T* pt1 = new T;
// right now, we own the allocated object
// pass ownership to an auto_ptr
auto_ptr<T> pt2( pt1 );
// use the auto_ptr the same way
// we'd use a simple pointer

*pt2 = 12;       // same as "*pt1 = 12;"

Releasing


...
// use release() to take back ownership
T* pt3 = pt2.release(); // pt3 = pt1 --> points to T object
// delete the object ourselves, since now
// no auto_ptr owns it any more

delete pt3;

Reset


To substitute the pointer owned by auto_ptr with another one, one would use auto_ptr's reset() method:

auto_ptr<T> pt( new T(1) );
pt.reset( new T(2) );
// deletes the first T that was
// allocated with "new T(1)"
 It internally calls delete on T(1) and create a new auto_ptr on T(2).

Notes


  • Never put auto_ptr into standard containers

vector< auto_ptr<T> > v; // No !!!

The problem is that auto_ptr does not quite meet the requirements of a type you can put into containers, because copies of auto_ptrs are not equivalent

C++ : const at the end of function declaration

class User
{
    public:
        User();
        User(std::string name);
        void doSomething() const;

    protected:
        std::string m_name;
};


In .cpp:

void User::doSomething() const
{
    // code
}

The const keyword indicates that *this (the object) is const on the method call. This declaration tells you that the object will not be modified within this function (in the example above, doSomething() cannot modify m_name).

Note : In practice, this notation is just a promise that can be violated by the function (not advised though).

C++ : constructor initialization list

In the implementation of the constructor, it is possible to initialize internal members with an initialization list. It is basically a list of parameters following a semicolon (:) with their initialization values :

Basic initialization


class Something
{
private:
    int m_nValue;
    double m_dValue;
    int *m_pnValue;

public:
    Something()
    {
        m_nValue = 0;
        m_dValue = 0.0;
        m_pnValue = 0;
    }
};


With an initialization list


class Something
{
private:
    int m_nValue;
    double m_dValue;
    int *m_pnValue;

public:
    Something() : m_nValue(0), m_dValue(0.0), m_pnValue(0)
    {
    }
};


Note : This syntax can be used with const member as well. For instance, if m_nValue was a const, it would had the same effect.

Thursday, November 26, 2015

C++ : Private pure virtual method

class Engine
{
public:
    void SetState( int var, bool val );
    {   SetStateBool( int var, bool val ); }

    void SetState( int var, int val );
    {   SetStateInt( int var, int val ); }
private:
    virtual void SetStateBool(int var, bool val ) = 0;   
    virtual void SetStateInt(int var, int val ) = 0;   
};

Although they are private, private virtual functions can be overridden in the derived classes.
This
"allows for better separation of the specification of interface from the specification of the implementation's customizable behavior
(Herb Sutter).

Why ?


Imagine that the clas was written like this, with non-pure virtual methods :

 class Engine
{
private:
    virtual void SetState(bool val ) { // blablablabla };   
    virtual void SetState(int val )
{ // blablablabla };   
};
 and consider the following child class which overloads one method only:

 class MyEngine : public Engine
{
public:
    void SetState(int val )
{ // blablablabla };   
};

One would get in trouble by calling :

MyEngine* myEng = new MyEngine();
myEng->SetState(true);

This statement would  call SetState(int val), converting bool to int.
To have a proper inheritance, the child class shall use the using keyword to hide base class method:

class MyEngine : public Engine
{
          // To prevent SetState( int var, bool val ) from the base class,
          // from being hidden by the new implementation of the other overload

          // (below),
          // you have to put using declaration in the derived class

         using Engine::SetState;

public:
    void SetState(int val )
{ // blablablabla };   
};

This is something that the developer should always keep in mind and it can end to unexpected behaviors if not applied.
With private non-virtual, the developer could have written the first version of derived class without caring about non-hidden methods.

C++ : Inheritance types

class A
{
public:
    int x;
protected:
    int y;
private:
    int z;
};

class B : public A
{
    // x is public
    // y is protected
    // z is not accessible from B
};

class C : protected A
{
    // x is protected
    // y is protected
    // z is not accessible from C
};

class D : private A
{
    // x is private
    // y is private
    // z is not accessible from D
};

 Note that x,y and z exists in all subclasses but are not accessible in all cases.

Thursday, November 12, 2015

C++ : copy constructor

We already know the basic constructor utility which is : initializing internal members. If not constructor is specified, the default constructor initializes each of class' members with their constructor.

Now let's take a look to the copy constructor :

Point (const Point & p);

This constructor will initialize our object by copying another one :

Point p1 (otherPoint);

Note: It is also possible to define our own copy constructor to define more specifically which members should be copied.

Monday, November 9, 2015

c++ : lvalue and rvalue

l-value

C-definition

An object is a manipulatable region of storage; an lvalue is an expression referring to an object....The name 'lvalue' comes from the assignment expression E1 = E2 in which the left operand E1 must be an lvalue expression.
 C Programming Language (Prentice-Hall, 1988)

r-value


C-definition


What is sometimes called 'rvalue' is in this standard described as the 'value of an expression'.
C-Standard 

C++ definition


Every expression is either an lvalue or an rvalue.
C++ 2003 Standard 

Translation

lvalues and rvalues got their names from their roles in assignment expressions 
lvalues refers to objects and are addressable.

int a; // lvalue
char* p;
// *p is an lvalue. '*' operator returns an l-value
*p = 'c'; // OK, we can assign an l-value
*(p + 1) = 'd'; // OK

Conceptually, an rvalue is just a value; it doesn't refer to an object

int a = 5; // 5 is an rvalue
int b = 8; // 8 is an rvalue
State_te state = State_Idle; // State_Idle is an rvalue;

5 = b; // Error ! we can not assign an rvalue
State_Idle = 8; // Error ! we can not assign an rvalue
a = &5; // Error ! & Operator requires an lvalue and returns an rvalue
&b = 8; // Error ! & returns an rvalue 

Note: In C++, rvalues can refer to objects but are still not lvalues.

 
biz.