Jump to content
3 posts in this topic

Recommended Posts

Hey Guy, I come from a C background, i know a little C++(well mostly C with Classes not proper C++) and I'm wondering if i should make the switch to the higher up C++? is it worth the jump or should i stick with C? C++ doesn't seem that hard i just don't understand what all the fuss is all about, and what benefits will i have by bumping up to the higher language?

Link to comment
Share on other sites

  • 2 weeks later...

C++11 introduces std::unique_ptr, std::shared_ptr, type_traits, move constructor, lambda's, auto and decltype, for-ranged loop and a few other things..

 

For example, in C++, you usually allocate memory using  raw pointers such as blah* ptr = new blah(); However, this can be dangerous because if an exception occurs or you forget to free it, you end up leaking the memory.. You'll have to cover every case to make sure you free it at any branches that may abruptly escape the scope the memory was allocated in..

 

However, with the RAII pointers above, you can do:  std::unique_ptr<blah> ptr(new blah()); and forget about ever freeing it because when this goes out of scope, it will automatically free the pointer for you. You can use this just like a regular pointer. It also has no overhead.. and you may also specify a "custom deleter" if your class requires a special function for freeing allocated memory.

 

std::shared_ptr is just like unique_ptr but is a reference counted pointer and will automatically free the memory when the reference count hits 0. This pointer type also allows you to delete dynamically created classes via pointer type without said class having a virtual destructor for one level of inheritance.

 

 

The move constructor and move assignment operators "move" an object instead of copying it. This allows you to write more efficient code and avoid problems that often occurred in C++98. It works by swapping the resources of one class with a dummy class and leaving the dummy in a destructible state. Think of it as stealing another class's resources and leaving the class to be an empty shell and ready to be destructed. It's literally an extremely efficient swap.

 

 

auto and decl type allow for type-deduction. For example, instead of doing:

 

for (std::vector<blah>::iterator it = ptr.begin(); it != ptr.end(); ++it)

 

you can replace it with:   for (auto it = ptr.begin(); it != ptr.end(); ++it) and the compiler will automatically deduce the type of "it" to be an iterator.

 

Another thing is that with the introduction of C++11, there is the decltype:

 

int a = 100;

decltype(a) b = 200;

 

this makes "a" the same type as "b" by deducing its type automatically. This is especially useful when dealing with templates or extremely long declarations.. Reduces typing quite a lot.

 

 

For-Ranged-Loop:

 

for (int it : some_vector)

{

     //do something with element it.

}

 

Says to iterate over some vector and assign its value to it for the declaration of the for-loop. This can be combined with references and auto and whatever you want..

 

for (auto &it : some_container) //works with arrays as well..

{

}

 

 

Next comes lambdas.. This allows you to declare functions inside functions:

 

void foo()

{

      auto search = [&](const Foo& f) -> bool {  //the [&] means capture variables by reference.. [=] means copy variables..

           //do something here..

           return true;

      };

 

      bool res = search(something); //use our lambda..

}

 

 

This also introduces std::function to allow you to take a function as a parameter:

 

void foo(std::function<void(const foo&)> func,   std::function<void()> func2)

{

        func(some_foo_parameter);

        func2();

}

 

 

 

Together, both lambda's and std::function's allow you to capture variables.. Meaning that you can pass a function some parameters and it will store them and you may then call said function at a later date without passing in any parameters.. For example:

 

 

std::function<void()> foo = std::bind(some_func, 100, 200);

foo(); //calls "some_func" and passes it 100, 200 as parameters..

 

std::function<void()> foo2 = std::bind(some_func, 100, std::placeholder_1);

foo(200); //calls "some_func" and passes it 100, 200 as parameters.

 

 

This allows for delayed function calling..

 

 

The next thing is variadic templates:

 

template<typename T, typename... Args>

void custom_printf(T a, Args... args)

{

        //unpack args and print them here..

}

 

Can be used in conjunction with std::tuple..

 

For type_traits, this allows you to o all sorts of template magic. For example, enabling a function if a template argument causes some condition to be true.

 

 

template<typename T>

class foo

{

    public:

         template<typename U = T, std::enable_if<std::is_same<int, T>::value>::type>

         void func()

         {

         }

};

 

 

This means that the "foo" class will only contain "func" IF AND ONLY IF  "T" is of type "int".

 

There are many many more type-traits such as those allowing you to determine whether or not a class contains a function, etc.. etc..

 

Also, there's const expressions but you can look that up. It's used for const-correctness and also allows the compiler to determine whether or not something can be calculated at compile-time or run-time..

 

std::regex, allocator_traints, etc.. are other additions..

 

There's so much more power in the language.. C++14 introduces even MORE! And C++17 will be another major update.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

C++11 introduces std::unique_ptr, std::shared_ptr, type_traits, move constructor, lambda's, auto and decltype, for-ranged loop and a few other things..

 

For example, in C++, you usually allocate memory using  raw pointers such as blah* ptr = new blah(); However, this can be dangerous because if an exception occurs or you forget to free it, you end up leaking the memory.. You'll have to cover every case to make sure you free it at any branches that may abruptly escape the scope the memory was allocated in..

 

However, with the RAII pointers above, you can do:  std::unique_ptr<blah> ptr(new blah()); and forget about ever freeing it because when this goes out of scope, it will automatically free the pointer for you. You can use this just like a regular pointer. It also has no overhead.. and you may also specify a "custom deleter" if your class requires a special function for freeing allocated memory.

 

std::shared_ptr is just like unique_ptr but is a reference counted pointer and will automatically free the memory when the reference count hits 0. This pointer type also allows you to delete dynamically created classes via pointer type without said class having a virtual destructor for one level of inheritance.

 

 

The move constructor and move assignment operators "move" an object instead of copying it. This allows you to write more efficient code and avoid problems that often occurred in C++98. It works by swapping the resources of one class with a dummy class and leaving the dummy in a destructible state. Think of it as stealing another class's resources and leaving the class to be an empty shell and ready to be destructed. It's literally an extremely efficient swap.

 

 

auto and decl type allow for type-deduction. For example, instead of doing:

 

for (std::vector<blah>::iterator it = ptr.begin(); it != ptr.end(); ++it)

 

you can replace it with:   for (auto it = ptr.begin(); it != ptr.end(); ++it) and the compiler will automatically deduce the type of "it" to be an iterator.

 

Another thing is that with the introduction of C++11, there is the decltype:

 

int a = 100;

decltype(a) b = 200;

 

this makes "a" the same type as "b" by deducing its type automatically. This is especially useful when dealing with templates or extremely long declarations.. Reduces typing quite a lot.

 

 

For-Ranged-Loop:

 

for (int it : some_vector)

{

     //do something with element it.

}

 

Says to iterate over some vector and assign its value to it for the declaration of the for-loop. This can be combined with references and auto and whatever you want..

 

for (auto &it : some_container) //works with arrays as well..

{

}

 

 

Next comes lambdas.. This allows you to declare functions inside functions:

 

void foo()

{

      auto search = [&](const Foo& f) -> bool {  //the [&] means capture variables by reference.. [=] means copy variables..

           //do something here..

           return true;

      };

 

      bool res = search(something); //use our lambda..

}

 

 

This also introduces std::function to allow you to take a function as a parameter:

 

void foo(std::function<void(const foo&)> func,   std::function<void()> func2)

{

        func(some_foo_parameter);

        func2();

}

 

 

 

Together, both lambda's and std::function's allow you to capture variables.. Meaning that you can pass a function some parameters and it will store them and you may then call said function at a later date without passing in any parameters.. For example:

 

 

std::function<void()> foo = std::bind(some_func, 100, 200);

foo(); //calls "some_func" and passes it 100, 200 as parameters..

 

std::function<void()> foo2 = std::bind(some_func, 100, std::placeholder_1);

foo(200); //calls "some_func" and passes it 100, 200 as parameters.

 

 

This allows for delayed function calling..

 

 

The next thing is variadic templates:

 

template<typename T, typename... Args>

void custom_printf(T a, Args... args)

{

        //unpack args and print them here..

}

 

Can be used in conjunction with std::tuple..

 

For type_traits, this allows you to o all sorts of template magic. For example, enabling a function if a template argument causes some condition to be true.

 

 

template<typename T>

class foo

{

    public:

         template<typename U = T, std::enable_if<std::is_same<int, T>::value>::type>

         void func()

         {

         }

};

 

 

This means that the "foo" class will only contain "func" IF AND ONLY IF  "T" is of type "int".

 

There are many many more type-traits such as those allowing you to determine whether or not a class contains a function, etc.. etc..

 

Also, there's const expressions but you can look that up. It's used for const-correctness and also allows the compiler to determine whether or not something can be calculated at compile-time or run-time..

 

std::regex, allocator_traints, etc.. are other additions..

 

There's so much more power in the language.. C++14 introduces even MORE! And C++17 will be another major update.

Thank you, that clears that up for me :)

Link to comment
Share on other sites

 Share

×
×
  • Create New...