Tag Archives: C++11

How to concatenate a string and an int in C++

Methods

  • Use std::stringstream
  • Use boost::lexical_cast()
  • Use boost::format()
  • Use std::to_string() (C++11)

Method 1. Use std::stringstream

#include <sstream>

std::stringstream ss;
ss << name << age;
result = ss.str();

Method 2. Use boost::lexical_cast()

#include <boost/lexical_cast.hpp>

result = name + boost::lexical_cast<std::string>(age);

Reference: Boost.Lexical_Cast

Method 3. Use boost::format()

#include <boost/format.hpp>

result =  boost::str(boost::format("%s%d") % name % age);

Reference: Boost Format library

Method 4. Use std::to_string() (C++11)

result = name + std::to_string(age);

Method 5. Use folly::toAppend()

#include <folly/Conv.h>

result =  name;
folly::toAppend(age, &result);

Reference: folly/Conv.h

Related

Calling One Constructor from Another in C++

C++11 has added the ability to call one constructor from another, allowing you to combine the code in constructors. You just call the second constructor from the initialization list of the first:

class Fruit
{
public:
    Fruit(const std::string& name, int number)
        : name_(name), number_(number)
    {
    }
    Fruit(const std::string& name)
        : Fruit(name, -1)
    {
    }
private:
    std::string name_;
    int number_;
};

Unfortunately, there isn’t a way of doing this in C++03. Putting a constructor call in the initialization list is a syntax error, while putting it in the body of the constructor just creates a temporary object.

    Fruit(const std::string& name)
    {
        Fruit(name, -1); // This just creates a temporary object
    }

You can, however, combine constructors by using default parameters:

    Fruit(const std::string& name, int number=-1)
        : name_(name), number_(number)
    {
    }

Or you can do your initialization in an Init() function and have your constructors delegate to that:

    Fruit(const std::string& name, int number)
    {
        Init(name, number);
    }
    Fruit(const std::string& name)
    {
        Init(name, -1);
    }
    void Init(const std::string& name, int number)
    {
        name_ = name;
        number_ = number;
    }

There are a few disadvantages to the Init() method:

  • The fields will be default initialized in the constructor before being initialized again in the Init() function
  • The values initialized in the Init() function cannot be passed to base class constructors that need them because it’s too late at that point (although the base class itself might have an Init function)
  • You can’t initialize const pointer or reference members this way, because they need to be initialized in the initialization list

How to convert an int to a std::string in C++

Methods

  1. Use std::stringstream
  2. Use boost::lexical_cast
  3. Use folly::to()
  4. Use std::to_string (C++11)

Method 1: Use std::stringstream

#include <sstream>

template <typename T>
std::string to_string(const T& thing)
{
    std::stringstream ss;
    ss << thing;
    return ss.str();
}

template <>
std::string to_string<std::string>(const std::string& s)
{
    return s;
}

std::cout << ::to_string(n) << "\n";

Method 2: Use boost::lexical_cast

#include <boost/lexical_cast.hpp>
std::cout << boost::lexical_cast<std::string>(n) << "\n";

Reference: Boost.Lexical_Cast

Method 3: Use folly::to()

#include <folly/Conv.h>
std::cout << folly::to<std::string>(n) << "\n";

Reference: folly/Conv.h

Method 4: Use std::to_string (C++11)

std::cout << std::to_string(n) << "\n";

Related

Lambda expressions in C++

The STL provides the useful std::for_each, and std::transform algorithms, which make it easy to iterate over sequences without needing to write a loop. They’re especially useful when you’re using existing free functions, static functions, and member functions:

// If v contains MyClass objects
std::for_each(v.begin(), v.end(), &FreeFunction);
std::for_each(v.begin(), v.end(), &MyClass::StaticFunction);
std::for_each(v.begin(), v.end(), std::mem_fun_ref(&MyClass::MemberFunction));

// If v contains pointers to MyClass objects
std::for_each(v.begin(), v.end(), std::mem_fun(&MyClass::MemberFunction));

Often however, there isn’t an existing function to do what you want, and you end up defining a function or function object just where you use it:

namespace {
    struct FunctionObject {
        void operator()(MyClass& m) {
            // Do something to m here
        }
    };
};

std::for_each(v.begin(), v.end(), FunctionObject());

Things can get more awkward still when you have local variables that you want to use in the operation you’re performing:

namespace {
    struct FunctionObject2 {
        typedef MyClass first_argument_type;
        typedef int second_argument_type;
        typedef void result_type;
        void operator()(const MyClass& m, int x) const 
        {
            // Do something with m and x here
        }
    };
};

int x;
std::for_each(v.begin(), v.end(), std::bind2nd(FunctionObject2(), x));

This is rather complicated for a one-shot piece of code. It would be much better to be able to define the operation to be performed in-line at the point of use, and this is what lambda expressions allow you to do.

For example, this lambda expression replaces our first example:

std::for_each(v.begin(), v.end(), [](MyClass& m) { /* Do something to m here*/ });

The [] can capture local variables, making them available within the body of the lambda expression. This is how our second example would look:

int x;
std::for_each(v.begin(), v.end(), [x](MyClass& m) { /* Do something with m and x here*/ });

Smart pointers

The standard library and Boost smart pointers fall into two types: scoped pointers and reference counted pointers.

Scoped pointers

boost::scoped_ptr and std::unique_ptr
The object is destroyed when the pointer instance goes out of scope.
They cannot be copied (although you can pass them by reference)
The lifetime of the object is tied either to:

  • The current scope
  • The lifetime of the containing object

The second of these makes them suitable for storage in containers.
The old std::auto_ptr is like a scoped pointer, except that it can be copied, which transfers ownership.
It is deprecated in the newer standards and should not be used.

Reference counted pointers

boost::shared_ptr and std::shared_ptr
Allows the pointer to be copied.
Useful when the lifetime of the object is more complicated.
Potential problems:

  • Creating them on the heap
  • Passing them by reference
  • Creating circular references

The last point is mitigated by boost::weak_ptr and std::weak_ptr, which define a weak (i.e., uncounted) reference to a shared_ptr.

Move semantics in C++

Consider the following simple string class:

class String
{
public:
    String()
        : data_(strdup_("")), len_(0)
    {
    }

    String(const char* str)
        : data_(strdup_(str)), len_(std::strlen(data_))
    {
    }

    String(const char *str, size_t len)
        : data_(strndup_(str, len)), len_(len)
    {
    }

    String(const String& other)
        : data_(strdup_(other.data_)), len_(other.len_)
    {
    }

    ~String()
    {
        delete[] data_;
    }

    String& operator=(String other)
    {
        std::swap(data_, other.data_);
        return *this;
    }

    String& operator+=(const String& other)
    {
        size_t len = len_ + other.len_;
        char *data = new char[len + 1];
        std::strcpy(data, data_);
        std::strcat(data, other.data_);
        delete[] data_;
        data_ = data;
        len_ = len;
        return *this;
    }

    String substring(size_t start, size_t len)
    {
        if (start < len_ - 1 && len <= len_ - start) {
            return String(&data_[start], len);
        }
        return String();
    }

    friend String operator+(String lhs, const String& rhs);
    friend std::ostream& operator<<(std::ostream& os, const String& str);

private:
    char* data_;
    size_t len_;
};

The important things to note are:

  • It manages a dynamically allocated block of memory, so it needs to observe the Rule of Three
  • In addition to its constructors, it has two functions that return an object: operator+(), and substring()

Now consider the following uses of the class:

int main()
{
    String a = "The quick brown fox jumps over";
    String b = " the lazy dog";

    String x = a;                  // Copy an existing object
    String y = a + b;              // Create a new object by addition and then copy it
    String z = a.substring(16, 3); // Create a new object by function call and then copy it

    std::cout << x << "\n";
    std::cout << y << "\n";
    std::cout << z << "\n";
}

There are 3 copying operations in this code. In the first, we are copying the instance a, so we naturally expect to be able to use a again after the copy has been made.
In the other two though, temporary objects are created (by operator+() and substring respectively), and there is no way we could use them before they are destroyed at the end of the expression. These temporary objects are called rvalues because they only occur on the right-hand side of an expression, and can never be on the left-hand side of one.

As these objects can never be used, it’s wasteful and unnecessary for them to go through the same construction and destruction process as objects we do use. In particular, it shouldn’t be necessary to go through the process of copying the data_ member in the copy constructor, only for it to be deleted immediately after the copy is made.

What move semantics provide, amongst other things, is a way of writing a copy constructor that behaves differently when the object being constructed is an rvalue, called a move constructor. Below is a move constructor for our string class:

String(String&& other)
{
    data_ = other.data_;
    other.data_ = nullptr;
}

Note the &&, which indicates an rvalue reference variable. It is this that makes the constructor a move constructor. This constructor will be called in the situations like those above where the compiler can tell that the object being copied is an rvalue. In this case we can simply steal the data_ member from the soon-to-be-destroyed other object by making it the data_ member of the new object, and then setting it the other object’s member to nullptr so that the block won’t be deleted when the other object goes out of scope. This makes the whole process of copy initialisation much more efficient when the object being copied is an rvalue.

There is a lot more to rvalues and move semantics than this, but as a first step it is well worth considering adding a move constructor to a class that has methods that return an object, as these objects are quite likely to be constructed as rvalues in practice.