C/C++ tips

What’s here ?

Here you will find some tips n tricks around C++.

Ternary

[source,cpp]

bool test = true;

(test) ? std::cout « “yes” : std::cout « “no”; // will print yes


Get int* len on linux and windows

[source,cpp]

#include #include

#ifdef linux #define array_size(x) malloc_usable_size(x) #endif

#ifdef _WIN32 #define array_size(x) _msize(x) #endif

int main(int argc, char*argv) { int len; int *array = malloc(sizeof(int)10);

len = array_size(array);
len = len / 4; 				// because array_size return size_t

printf("len : %d\n", len);
return(0); } ----

Two ways to iterate

[source,cpp]

std::vector latWayPoints; // fill vector

for (std::vector::iterator it = latWaypoints.begin(); it != latWaypoints.end(); ++it) qDebug() << ">> latWay : " << *it;

for (double lon: lonWaypoints) qDebug() « ”» latWay : “ « lon; —-

cpp method callable from qml

[source,cpp] —-

// .h Q_INVOKABLE void my_function();

//.cpp void my_class::my_function() { // do stuff }

//.qml onMyEvent: { item.my_function(); } —-

cast

dynamic_cast pour les classes héritées surtout, static_cast pour les types de base, reinterpret_cast pour forcer un cast de n’importe quoi vers n’importe quoi et const_cast pour pouvoir passer des string en entrée à des vieilles fonctions C qui veulent des char*

Concat arrays C style in C++

[source,cpp]

void concatArrays(unsigned char * &src, int dstOffset, unsigned char * dst) { int j = 0; int i = 0; int srcLen = strlen(reinterpret_cast<char *>(src)); int dstLen = strlen(reinterpret_cast<char *>(dst)); unsigned char * tmp = new unsigned char [srcLen + dstLen + 1];

for (i = 0; i < srcLen; ++i)
{
   tmp[i] = src[i];
}

i = dstOffset;

while (j < dstLen && i < (srcLen + dstLen + 1))
{
    tmp[i] = dst[j];
    i++;
    j++;
}

delete [] src;
src = tmp; }

void test(unsigned char * buffer, unsigned char * append) { std::cout « “buffer : “ « buffer « std::endl; concatArrays(buffer, 4, append); std::cout « “buffer -> : “ « buffer « std::endl; }

int main() { char * buffer = new char [5]; char * append = new char [10];

strcpy(buffer, “tato”); strcpy(append, “chipolata”);

test(reinterpret_cast<unsigned char *>(buffer), reinterpret_cast<unsigned char *>(append)); } —-

Pragma and warnings

You can use pragma to lower the warnings level at build time or to disable some kinds of warnings.

[source, cpp]

#pragma warning(push,0) // here include libs that you can’t touch and you don’t want build warnings from #include #pragma warning(pop)

// To disable the warnings “deprecated” for C functions like strcpy under windows

#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4996) #endif

strcpy(); #ifdef _MSC_VER #pragma warning(pop) #endif —-

Create a class to not include it

When you have namespace tata with in it namespace tutu and in it a class myClass and you want to have a pointer of myClass type in a class, to faster the build in .h don’t include the “myClass.h”, include it only in cpp and prefer this way :

[source,cpp]

include

namespace tata { namespace tutu { class myClass; }}

class testClass { public: testClass();

private: tata::tutu::myClass * _myPtr; };


Random between min and max

[source,cpp] —- #include #include

int main() { int min = 5; int max = 10;

srand(time(NULL)); int random = ( rand() % ( max - min + 1 ) ) + min; std::cout « random « std::endl; } —-

=== osg geometry usage

[source,cpp]

#include <osgEarthFeatures/Feature> #include <osgEarthFeatures/GeometryUtils>

std::string wkt_geom; // geom at wkt format

osgEarth::Symbology::Geometry geom = osgEarth::Features::GeometryUtils::geometryFromWKT(wkt_geom);


=== map iterations [source, cpp] —- QMap<QString, QString> myMap;

for (auto map : myMap.toStdMap()) { qDebug() « “key : “ « map.first « ” value : “ « map.second; }

for (auto mapKey : myMap.keys()) { qDebug() « “key : “ « mapKey « ” value : “ « myMap.value(mapKey); } —-

=== Const

===== const function

[source, cpp]

int foo::bar(int random_arg) const; // can be understood as a declaration with a this const pointer // -> no modification of member variables are possible. —-

A “const function”, denoted with the keyword const after a function declaration, makes it a compiler error for this class function to change a member variable of the class. However, reading of a class variables is ok inside of the function, but writing inside of this function will generate a compiler error.

===== const returned value

In C, because function return values, and qualifying values is meaningless. It may be different in C++, check other answers.

[source, cpp]

const int i = (const int)42; /* meaningless, the 42 is never gonna change / int const foo(void); / meaningless, the value returned from foo is never gonna change */

// Only objects can be meaningfully qualified.

const int ip = (const int *)&errno; / ok, ip points to an object qualified with const / const char *foo(void); / ok, foo() returns a pointer to a qualified object */ —-

Note that for class types, the const for return values is not meaningless, as you are allowed to call modifying member functions on non-const rvalues. (We just had this here with strings the other day: (s1+s2).append(s3).) As usual, litb’s answer explains all this both in detail and correctness.

pointers handling

scope and unique_pointer

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

std::unique_ptr instances cannot be copied. This prevents the pointer from being deleted multiple times (incorrectly). You can, however, pass references to it around to other functions you call.

std::unique_ptrs are useful when you want to tie the lifetime of the object to a particular block of code, or if you embedded it as member data inside another object, the lifetime of that other object. The object exists until the containing block of code is exited, or until the containing object is itself destroyed.

shared ptr

A more complex smart pointer policy involves reference counting the pointer. This does allow the pointer to be copied. When the last “reference” to the object is destroyed, the object is deleted.

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.
  

Reference counted pointers are very useful when the lifetime of your object is much more complicated, and is not tied directly to a particular section of code or to another object.

There is one drawback to reference counted pointers — the possibility of creating a dangling reference:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

// another possibility is to create circular references
struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

weak_ptr

same as above, but it’s a ‘slave’ for a shared_ptr, can’t deallocate