let’s dev GmbH & Co. KG - The brand for groundbreaking custom software

Blog

Top!

let’s dev | Scroll to top
let’s dev | Scroll to next content item

Hello

let’s dev | Scroll to previous content item
let’s dev Blog | Smart Pointer in C++
by Matthias
01. April 2018

Smart Pointer in C++

The purpose of this blog post is to provide an insight into the use of Smart Pointers (Shared Pointers in C++) and the most important basics. The following explanations aim to provide a quick introduction to this topic.

Introduction

In the introductory chapter, the necessity of shared pointers is first clarified and their use is motivated. It is not without reason that shared pointers are a standard language feature in some high-level programming languages, such as ARC (Automatic Reference Counting) in Objective-C.

Smart Pointer in C++

Readers who already have basic knowledge and are interested in an executable code snippet are recommended to start directly at chapter 2 Basics of shared_ptr. This explains the use of shared pointers with the help of examples.

Introduction - The Mystery of Shared Pointers in C++

"Why can't you just use shared pointers? Shared pointers are a very clever way to manage pointers and memory."

You hear this statement very often. But are shared pointers already really being used on a larger scale and consistently in projects? In discussions with developers, one quickly gets the impression that shared pointers are not particularly widespread or popular. What is the reason for this? Are there problems that occur more frequently during use? Are shared pointers too complicated to understand or is it too much effort to use them?

We hope this post will help clarify some of the questions surrounding the mystery of shared pointers and provide a good example of how to use them correctly.

Introduction - An Analogy to Shared Pointers

Instead of jumping straight into technical details, the use of shared pointers is first explained using a real-life example:

Imagine you work in a company and there is a simple rule for the office building: the last employee who leaves the building must lock the entrance door to the building and activate the alarm system. If someone leaves the building and the alarm system is already activated, then the alarm will be triggered. Therefore, you should carefully check if there is someone else in the building before activating the alarm system.

Assuming the office building consists of only one small room and there are only five employees, it is very easy for you to determine if you are the last employee left in the building. However, imagine you are working in a huge office building with several floors and many hundreds of employees. In order to know if you are the last person in the building, you would have to search all floors and all rooms. Now consider, someone else is searching the building at the same time to see if anyone else is in the building and they both miss each other as a result. You end up accidentally locking the other person in the building with the alarm system activated. What a mess!

But what if there was a kind of "smart door" to the building, which adds +1 for each person entering the building and subtracts -1 for each person leaving the building. So as soon as the counter reading reaches 0, the alarm system is automatically activated.

Wouldn't that be a great solution to this problem? The idea behind the Shared Pointers is similar to the "Smart Door" from the example explained.

Introduction - The use of C++ shared_ptr

When programming in C++ it is often not easy to keep track of the memory management of the entire source code of a project. Once a C++ pointer has been created, the following questions often arise:

The simple answer to these questions is usually the following statement:

"The pointer is deleted at the point in the program where it was last used."

But as in the example from 1.2, where it is not possible to determine unambiguously how many people are in a large building and where exactly they are, it is by no means easy to keep track of where all the pointers in a program have been forwarded to.

"How do you know which is the last place a pointer was used?"

A pointer could possibly have been passed on by several constructors or methods parameters. In addition, it could be that one works together with several teammates on the same source code.

Comparing the handling of pointers in C++ with the example from 1.2, calling the delete command on a pointer for which memory has already been freed would be equivalent to trying to leave the building in which the alarm system has already been activated. As soon as one tries to open the door from the inside, the alarm system would be triggered and the program would crash for the pointers.

Which is the last place a pointer was used and knowing at what time to call delete is not a question that can be answered so easily, as long as there is a third instance that takes care of this task. And with this third instance Shared Pointer, like the std::shared_ptr come into play.

The shared pointer knows exactly which is the last place where a pointer was used and as soon as a pointer was used for the last time in the whole program, it is automatically deleted. This happens every time someone creates a copy, e.g. when the shared pointer is passed as a parameter in a method or in a constructor. Furthermore, -1 is always subtracted if the object that used the shared pointer has been deleted or the method that used the shared pointer has been terminated. As soon as the value 0 is reached, the pointer is automatically deleted and the occupied memory is released again.

Basics of shared_ptr

In the following some code examples are presented. Due to the clarity, the office example from chapter 1.2 is taken up again here:

First, an OfficeBuilding class is defined, i.e. a building that can be entered by employees. This means that an OfficeBuilding can reference multiple instances of an Employee object. And as a small, additional feature, there is a washroom in the building, which can be entered by exactly one employee.

Database relations

Basics of shared_ptr - instantiation of a shared_ptr

For example, if you wanted to create an instance of an object Employee, you would normally instantiate a pointer using the new keyword to allocate heap memory. The delete keyword would be used to free the memory:

Employee  *employee1 = new Employee( 1, “Peter Parker”);
delete employee1;
These two lines of code are now replaced by the following:
shared_ptr<Employee> employee1 = make_shared<Employee>(1, "Peter Parker");

The left side of the assignment shared_ptr<Employee> employee1 holds an instance of the Employee class and instead of using the new keyword, you use the make_shared keyword to create that instance.

The parameters that one would normally pass to the constructor of the Employee class are instead passed to the expression shared_ptr<Employee> (parameter1, parameter2, ...).

As soon as the current context is left, e.g. the context of the currently called method, the memory that was occupied by the employee1 instance is automatically freed. The call of the delete command is therefore not necessary.

basics of shared_ptr - access to class members of a shared pointer

Suppose you want to access the name of the variable employee1 using the getter method, you could do this by treating the variable like a normal C++ pointer and using the arrow operator "->":

string employeeName = employee1->getName();

In contrast, using the dot operator "." grants access to useful information about the shared reference, such as the number of reference counts:

long employee1UseCount = employee1.use_count();

Theoretically, it is also possible to access the raw pointer, which is managed by the shared pointer, via the shared pointer:

Employee *pointer = employee1.get();

However, access to the raw pointer, as in this example, should be avoided at all costs, because this again only leads to well-known problems: someone tries to free memory that has already been freed. This possibility should be mentioned here only for the sake of completeness.

Basics of shared_ptr - copying a shared_ptr

How to make a copy of a shared_ptr which points to allocated memory? Comparing it to normal pointers, one would normally write the following:

Employee  *employee1 = new Employee( 1, “Peter Parker”);
Employee  *employee1Copy = employee1;

The first line of code allocates an Employee object and has the pointer employee1 point to the newly allocated memory. Then the second line makes a copy of this variable and the new variable employee1Copy then points to the same memory area as employee1. If you want to do something similar with a shared_ptr, then there are two possibilities:


shared_ptr<Employee> employee1 = make_shared<Employee>(1, "Peter Parker");

1) shared_ptr<Employee> employee1Copy = employee1;
2) auto employee1Copy2 = employee1;

How does reference counting behave?

Now that the basics about shared_ptr have been covered, it would be interesting next to look at how reference counting behaves in a real code example.

First, we will look at the Employee class. An employee has an attribute name and a unique id, which can be passed to the constructor. To keep the example as simple as possible, this class does not contain any pointers or shared pointers.

#ifndef SHAREDPOINTEREXAMPLEAPPLICATION_EMPLOYEE_H
#define SHAREDPOINTEREXAMPLEAPPLICATION_EMPLOYEE_H

#import <vector>
#import <string>
#import <iostream>
using namespace std;

class Employee {

private:
    int id;
    string name;
public:
    Employee(int id, const string &name) : id(id), name(name){
    }

    int getId() const{
        return id;
    }

    const string &getName() const{
        return name;
    }

    void printCurrentUseCount(shared_ptr<Employee> employee){
        if(employee.use_count() > 0){

            printf("%s, use count: %li n", getName().c_str(), (employee.use_count() -1));

        } else{
            printf("use count: %li n", employee.use_count());
        }
    }
};

#endif //SHAREDPOINTEREXAMPLEAPPLICATION_EMPLOYEE_H

To have a better overview of the Reference Counts, there is another method printCurrentUseCount. Since a new context is entered with each call of the method and thus the result would be "falsified" by the value +1, here again the result to be output is always lowered by -1.

The OfficeBuilding, in which the employees work, can be entered and left by calling the methods enterBuilding and leaveBuilding. On closer inspection, it is noticeable that the OfficeBuilding class has a class variable vector<shared_ptr<Employee>> smartDoorPeopleCounter, which remembers which employees are currently in the building.

The two methods useWashRoom and leaveWashRoom always allow exactly one employee to enter or leave the WC.

#ifndef SHAREDPOINTEREXAMPLEAPPLICATION_OFFICEBUILDING_H
#define SHAREDPOINTEREXAMPLEAPPLICATION_OFFICEBUILDING_H

#include "Employee.h"
#include "WashRoom.h"
#import <vector>
#import <string>
#include <thread>
#include <cstdlib>

class OfficeBuilding {

private:
    vector<shared_ptr<Employee>> smartDoorPeopleCounter;
    vector<WashRoom> washRoom;

public:
    void enterBuilding(shared_ptr<Employee> employeeWhoWantsToEnter) {
        smartDoorPeopleCounter.push_back(employeeWhoWantsToEnter);
        employeeWhoWantsToEnter->printCurrentUseCount(employeeWhoWantsToEnter);
    }

    void leaveBuilding(shared_ptr<Employee> employeeWhoWantsToLeave) {
        int indexToRemove = -1;
        for (int i = 0; i < smartDoorPeopleCounter.size(); i++) {
            auto currentEmployee = smartDoorPeopleCounter[i];
            if (currentEmployee->getId() == employeeWhoWantsToLeave->getId()) {
                indexToRemove = i;
            }
        }
        if (indexToRemove != -1) {
            smartDoorPeopleCounter.erase(smartDoorPeopleCounter.begin() + indexToRemove);
        }
        if (smartDoorPeopleCounter.size() == 0) {
            // activate alarm system
        }
    }

    void useWashRoom(shared_ptr<Employee> employee) {
        if (washRoom.size() == 0) {
            WashRoom emptyWashRoom;
            emptyWashRoom.setEmployee(employee);
            washRoom.push_back(emptyWashRoom);
        } else {
            //washroom is currently in use, please wait!
        }
    }

    void leaveWashRoom() {
        if (washRoom.size() == 1) {
            washRoom.clear();
        }
    }
};

#endif //SHAREDPOINTEREXAMPLEAPPLICATION_OFFICEBUILDING_H

The Washroom object always keeps a shared_ptr on the current employee who is currently using the WC.

#ifndef SHAREDPOINTEREXAMPLEAPPLICATION_OFFICEROOM_H
#define SHAREDPOINTEREXAMPLEAPPLICATION_OFFICEROOM_H

#include "Employee.h"

class WashRoom {
    shared_ptr<Employee> employee;
public:
    void setEmployee(const shared_ptr<Employee> &employee) {
        WashRoom::employee = employee;
    }

    const shared_ptr<Employee> &getEmployee() const {
        return employee;
    }
};

#endif //SHAREDPOINTEREXAMPLEAPPLICATION_OFFICEROOM_H

The following sample code allocates some employee objects (Employee) and lets them enter and leave the OfficeBuilding.


OfficeBuilding officeBuilding;

/* create employee 1 */
shared_ptr<Employee> employee1 = make_shared<Employee>(1, "Peter Parker");
employee1->printCurrentUseCount(employee1); //Peter Parker, use count: 1
string employeeName = employee1->getName(); // "Peter Parker"
Employee *pointer = employee1.get(); // attention: raw pointer should not be used!!
shared_ptr<Employee>  employee1Copy = employee1;
employee1->printCurrentUseCount(employee1); //Peter Parker, use count: 2
auto employee1Copy2 = employee1;
employee1->printCurrentUseCount(employee1); //Peter Parker, use count: 3

/* create employee 2 */
shared_ptr<Employee> employee2;
employee2->printCurrentUseCount(employee2); //use count: 0
employee2 = make_shared<Employee>(2, "Bruce Wayne");
employee2->printCurrentUseCount(employee2); //Bruce Wayne, use count: 1

/* create employee 3 */
auto employee3 = make_shared<Employee>(3, "Clark Kent");
employee3->printCurrentUseCount(employee3); //Clark Kent, use count: 1

/* employees entering building */
officeBuilding.enterBuilding(employee1); //Peter Parker, use count: 5
employee1->printCurrentUseCount(employee1); //Peter Parker, use count: 4
officeBuilding.enterBuilding(employee2); //Bruce Wayne, use count: 3
employee2->printCurrentUseCount(employee2); //Bruce Wayne, use count: 2
officeBuilding.enterBuilding(employee3);//Clark Kent, use count: 3
employee3->printCurrentUseCount(employee3);//Clark Kent, use count: 2

/* employee 1 entering using washroom */
officeBuilding.useWashRoom(employee1);
employee1->printCurrentUseCount(employee1); //Peter Parker, use count: 5
officeBuilding.leaveWashRoom();
employee1->printCurrentUseCount(employee1);//Peter Parker, use count: 4

/* employee 1 leaving building */
officeBuilding.leaveBuilding(employee1);
employee1->printCurrentUseCount(employee1);//Peter Parker, use count: 3

/* employee 1 visiting coffee house */
CoffeeHouse coffeeHouse;
coffeeHouse.visitCoffeeHouse(employee1);
employee1->printCurrentUseCount(employee1);//Peter Parker, use count: 4

bool finish = true;

The print editions here are intended to illustrate what the current Reference Count is in each case:

Peter Parker, use count: 1
Peter Parker, use count: 2
Peter Parker, use count: 3
use count: 0
Bruce Wayne, use count: 1
Clark Kent, use count: 1
Peter Parker, use count: 5
Peter Parker, use count: 4
Bruce Wayne, use count: 3
Bruce Wayne, use count: 2
Clark Kent, use count: 3
Clark Kent, use count: 2
Peter Parker, use count: 5
Peter Parker, use count: 4
Peter Parker, use count: 3
use count inside context: 5
use count outside context: 4
use count from thread: 6
use count after thread finished : 5
Peter Parker, use count: 4

The use of shared_ptr within threads

It is suspected that there could be problems related to threads when using C++ shared pointers. Below is also an example for this particular case: there is a cafe, which is located outside the OfficeBuilding and which an employee (Employee) can visit.

The cafe can be entered using the visitCoffeeHouse method. In this method, first the shared pointer to the employee is assigned to an auto variable and then to a shared pointer struct, which serves as a container for the parameters of the thread.


#ifndef SHAREDPOINTEREXAMPLEAPPLICATION_COFEEHOUSE_H
#define SHAREDPOINTEREXAMPLEAPPLICATION_COFEEHOUSE_H

#include "Employee.h"
#import <vector>
#import <string>
#include <thread>
#include <cstdlib>
#include <unistd.h>

using namespace std;
static pthread_t threadID = pthread_t();

class CoffeeHouse {

private:
    shared_ptr<vector<shared_ptr<Employee>>> cafeteriaCounter;
    struct threadParams {
        shared_ptr<Employee> employeeCopy;
        shared_ptr<vector<shared_ptr<Employee>>> cafeteriaCounterCopy;
    };

    static void *visitCoffeeHouseAsync(void *context) {

        unsigned int microseconds = 5000000; // sleep for 5 seconds
        usleep(microseconds);
        auto params = *(shared_ptr<threadParams> *) context;
        auto employee =  params->employeeCopy;
        string employeeName = employee->getName();

        if (employeeName.length() > 0) {
            params->cafeteriaCounterCopy->push_back(employee);
            printf("use count from thread: %li n", (employee.use_count()));
        }

        pthread_detach(pthread_self());
        return nullptr;
    }

public:

    CoffeeHouse(){
        cafeteriaCounter = make_shared<vector<shared_ptr<Employee>>>();
    }

    void visitCoffeeHouse(shared_ptr<Employee> employee) {
        {
            shared_ptr<threadParams> params = make_shared<threadParams>();
            params->employeeCopy = employee;
            params->cafeteriaCounterCopy = cafeteriaCounter;
            printf("use count inside context: %li n", (employee.use_count())); //use count inside context: 5
            pthread_create(&threadID, NULL, visitCoffeeHouseAsync, &params);
        }

        printf("use count outside context: %li n", (employee.use_count())); //use count outside context: 4
        pthread_join(threadID, NULL);
        printf("use count after thread finished : %li n", (employee.use_count()));//use count after thread finished : 5
    }
};

#endif //SHAREDPOINTEREXAMPLEAPPLICATION_COFEEHOUSE_H

The thread is started within a special context, where the context is marked by the curly braces { }. Within the context, the useCount will have the value 5 just before the thread is started. After the thread is started, the context is exited while the thread sleeps for 5 seconds and in the meantime the Reference Count is decreased to the value 4 by the Main Thread.

Once the thread wakes up again, it will make a local and a global copy of the shared pointer, resulting in the output of the value 6.

After the thread is terminated, only the global copy remains, resulting in an output of the value 5. The final result after exiting the visitCoffeeHouse method for the "Peter Parker" employee is the value 4.

At first glance, everything looks relatively normal with the threads. That is, the reference counts seem to be increased and decreased correctly. However, problems can never be completely ruled out. If you want to be completely sure, it is recommended to work only on a copy of the data.

Summary

The concept of C++ shared_ptr provides an alternative to traditional C++ pointers. However, it is crucial never to mix normal C++ pointers and shared pointers because this can lead to serious problems.

The great advantage of shared pointers, the automatic management of memory references, also replaces the tedious manual memory sharing. Furthermore, an insight was given into how reference counting behaves. Simply said: Whenever a new context is entered e.g. a method or a copy of a Shared Pointer, the Reference Count is increased by +1. As soon as a context is left again, the reference count is automatically reduced, depending on the number of copies in this context. After intensive familiarization with the topic, it can be stated that shared pointers can make the development process significantly more convenient and easier. They also make collaboration with team colleagues much easier. It should be exciting to use shared pointers in larger projects in the future.

However, there could be a small disadvantage: if you use shared pointers in a project and also want to use an external library such as OpenCV in the same project, which may not offer shared pointers in the interfaces, you should be very careful with it. It might be a good idea to use a "deep copy" of the data that you want to pass as parameters to the interfaces of the library.

Image credits:

  • iStock: kasto80

More articles from our blog

let’s dev Blog |

Technical

by Julian

2021-10-14

Read more
let’s dev Blog | Apple Developer Program: What is it used for and what content does it offer me as a member?

Corporate

Apple Developer Program: What is it used for and what content does it offer me as a member?

by Julian

2021-09-30

Read more
let’s dev Blog | Sketch, Figma & Co. - We take a look at the most popular UI and Prototyping Tools in 2021

Corporate

Sketch, Figma & Co. - We take a look at the most popular UI and Prototyping Tools in 2021

by Ellen

2021-07-15

Read more
let’s dev Blog | Tailwind: An innovative project for the future use of old wind turbines

Corporate

Tailwind: An innovative project for the future use of old wind turbines

by Karl

2021-06-24

Read more
let’s dev Blog |

Corporate

by Julian

2021-06-10

Read more
let’s dev Blog | Smart Prognosis of Energy with Allocation of Resources

Corporate

Smart Prognosis of Energy with Allocation of Resources

by Karl

2021-02-18

Read more
let’s dev Blog | Dasoman - Data-Sovereignty-Manager

Corporate

Dasoman - Data-Sovereignty-Manager

by Karl

2021-01-11

Read more
let’s dev Blog | We look back on the past months - And wish all the best for the coming year 2021!

Corporate

We look back on the past months - And wish all the best for the coming year 2021!

by Julian

2020-12-17

Read more
let’s dev Blog | iOS User Interface Tests

Technical

iOS User Interface Tests

by Nicolas

2020-11-12

Read more
let’s dev Blog | Adobe Max - Online for the first time

Corporate

Adobe Max - Online for the first time

by Julia

2020-10-29

Read more
let’s dev Blog | CAN2BLE

Technical

CAN2BLE

by Raphael

2020-09-24

Read more
let’s dev Blog | Mensch und Computer 2020 - Digital Change in the Flow of Time

Corporate

Mensch und Computer 2020 - Digital Change in the Flow of Time

by UX Team

2020-09-18

Read more
let’s dev Blog | Neumorphism – A new era of user interface design?

Technical

Neumorphism – A new era of user interface design?

by Julian

2020-08-13

Read more
let’s dev Blog | UX Research Part 3 - UX Methods

Technical

UX Research Part 3 - UX Methods

by Elena

2020-05-28

Read more
let’s dev Blog | UX Research Part 2 - What is UCD and what does User Research have to do with it?

Technical

UX Research Part 2 - What is UCD and what does User Research have to do with it?

by Elena

2020-04-23

Read more
let’s dev Blog | go-digital promotes establishment of home office workstations

Corporate

go-digital promotes establishment of home office workstations

by Karl

2020-03-19

Read more
let’s dev Blog | Google Passes - Card Management on Android Devices

Technical

Google Passes - Card Management on Android Devices

by Michelle

2020-03-12

Read more
let’s dev Blog | 100% code coverage in software testing - a reasonable goal?

Technical

100% code coverage in software testing - a reasonable goal?

by Raphael

2020-03-06

Read more
let’s dev Blog | Swift UI - Simple and fast implementation of user interfaces

Technical

Swift UI - Simple and fast implementation of user interfaces

by Tobias

2020-03-02

Read more
let’s dev Blog | In dialog with the business juniors - Exciting insights into business start-ups and digital transformation

Corporate

In dialog with the business juniors - Exciting insights into business start-ups and digital transformation

by Julian

2020-02-27

Read more
let’s dev Blog | Simplified testing of iOS push notifications in the simulator with Xcode 11.4

Technical

Simplified testing of iOS push notifications in the simulator with Xcode 11.4

by Manuel

2020-02-26

Read more
let’s dev Blog | National meeting of the consortium of the SPEAR research project at let's dev in Karlsruhe

Corporate

National meeting of the consortium of the SPEAR research project at let's dev in Karlsruhe

by Karl

2020-01-27

Read more
let’s dev Blog | UX Research Part 1 - Why User Research is so important

Technical

UX Research Part 1 - Why User Research is so important

by Elena

2020-01-23

Read more
let’s dev Blog | Dark Mode

Technical

Dark Mode

by Elisa

2020-01-09

Read more
let’s dev Blog | We wish you a Merry Christmas - And a Happy New Year!

Corporate

We wish you a Merry Christmas - And a Happy New Year!

by Julian

2019-12-20

Read more
let’s dev Blog | Exchange on the topic of digitization with the Business Club Luxembourg at the Embassy of Luxembourg in Berlin

Corporate

Exchange on the topic of digitization with the Business Club Luxembourg at the Embassy of Luxembourg in Berlin

by Karl

2019-12-17

Read more
let’s dev Blog | DaSoMan at the Internet+ Expo in Foshan (China)

Corporate

DaSoMan at the Internet+ Expo in Foshan (China)

by Karl

2019-12-13

Read more
let’s dev Blog | Google Play Console: Pre-Launch Reports

Technical

Google Play Console: Pre-Launch Reports

by Fabian

2019-12-11

Read more
let’s dev Blog | DevFest 2019 in Hamburg

Technical

DevFest 2019 in Hamburg

by Julian

2019-12-05

Read more
let’s dev Blog | Vernissage digital art in the media theater of the Humboldt University Berlin

Corporate

Vernissage digital art in the media theater of the Humboldt University Berlin

by Karl

2019-11-21

Read more
let’s dev Blog | World Usability Day 2019 in Karlsruhe - let's dev supports as main sponsor

Corporate

World Usability Day 2019 in Karlsruhe - let's dev supports as main sponsor

by Aileen

2019-11-11

Read more
let’s dev Blog | Gutted - Open Day at the Alter Schlachthof Karlsruhe 2019

Corporate

Gutted - Open Day at the Alter Schlachthof Karlsruhe 2019

by Julian

2019-09-26

Read more
let’s dev Blog | Mensch und Computer 2019 - Conference on User Experience and Usability in Hamburg

Corporate

Mensch und Computer 2019 - Conference on User Experience and Usability in Hamburg

by Elena

2019-09-17

Read more
let’s dev Blog | Business and Enterprise App Distribution on iOS

Technical

Business and Enterprise App Distribution on iOS

by Aileen

2019-08-05

Read more
let’s dev Blog | Digital Transformation - Chances and Challenges in the Automotive Industry, Agriculture and New Technologies

Corporate

Digital Transformation - Chances and Challenges in the Automotive Industry, Agriculture and New Technologies

by Karl

2019-07-17

Read more
let’s dev Blog | let's dev supports runners at the 7th KIT Championship

Corporate

let's dev supports runners at the 7th KIT Championship

by Karl

2019-07-05

Read more
let’s dev Blog | Automated testing of C++ code with Google Test and Google Mock - Part 2

Technical

Automated testing of C++ code with Google Test and Google Mock - Part 2

by Arne

2019-06-13

Read more
let’s dev Blog | Apple WWDC 2019: These are the highlights of the keynote

Technical

Apple WWDC 2019: These are the highlights of the keynote

by Nicolas

2019-06-05

Read more
let’s dev Blog | App Builders 2019

Technical

App Builders 2019

by Nicolas

2019-05-23

Read more
let’s dev Blog | Official opening of the Consolidation and Expansion Center (FUX)

Corporate

Official opening of the Consolidation and Expansion Center (FUX)

by Helena

2019-04-15

Read more
let’s dev Blog | Delegation from Nottingham to visit the Alter Schlachthof in Karlsruhe

Corporate

Delegation from Nottingham to visit the Alter Schlachthof in Karlsruhe

by Helena

2019-04-14

Read more
let’s dev Blog | The time has come: We are moving!

Corporate

The time has come: We are moving!

by Helena

2019-03-26

Read more
let’s dev Blog | Automated testing of C++ code with frameworks - part 1

Technical

Automated testing of C++ code with frameworks - part 1

by Arne

2019-02-20

Read more
let’s dev Blog | The app in the Google Play Store

Technical

The app in the Google Play Store

by Elisa

2019-01-24

Read more
let’s dev Blog | „UX Day“ 2018

Corporate

„UX Day“ 2018

by Aileen

2018-12-17

Read more
let’s dev Blog | let's dev supports SG Siemens volleyball players from Karlsruhe

Corporate

let's dev supports SG Siemens volleyball players from Karlsruhe

by Helena

2018-12-04

Read more
let’s dev Blog | SMEs shape digitalization - SME Conference 2018

Corporate

SMEs shape digitalization - SME Conference 2018

by Helena

2018-11-12

Read more
let’s dev Blog | Apple Wallet

Technical

Apple Wallet

by Maik

2018-10-26

Read more
let’s dev Blog | „Mensch und Computer“ 2018

Corporate

„Mensch und Computer“ 2018

by Judith

2018-09-24

Read more
let’s dev Blog | State Design Pattern in Android

Technical

State Design Pattern in Android

by Thomas

2018-09-17

Read more
let’s dev Blog | let's dev is an authorized consulting company in the „go-digital“ funding program

Corporate

let's dev is an authorized consulting company in the „go-digital“ funding program

by Helena

2018-09-01

Read more
let’s dev Blog | App Design & Development Conference 2018

Corporate

App Design & Development Conference 2018

by Helena

2018-08-14

Read more
let’s dev Blog | iOS 12: The top new features at a glance

Technical

iOS 12: The top new features at a glance

by Nicolas

2018-07-17

Read more
let’s dev Blog | let's dev at CEBIT

Corporate

let's dev at CEBIT

by Karl

2018-06-11

Read more
let’s dev Blog | Introduction to User Interface (UI) Testing with Espresso

Technical

Introduction to User Interface (UI) Testing with Espresso

by Raphael

2018-06-07

Read more
let’s dev Blog | The app in the Apple App Store: what information is needed?

Technical

The app in the Apple App Store: what information is needed?

by Aileen

2018-04-27

Read more
let’s dev Blog | User interface design for iPhone X: all innovations at a glance

Technical

User interface design for iPhone X: all innovations at a glance

by Helena

2018-02-07

Read more
let’s dev Blog | WebVR - Virtual Reality Experience in the Browser with the A-Frame Framework

Technical

WebVR - Virtual Reality Experience in the Browser with the A-Frame Framework

by Judith

2018-01-10

Read more
let’s dev Blog | Deutsche Bahn Open Data Hackathon

Corporate

Deutsche Bahn Open Data Hackathon

by Karl

2015-03-31

Read more
let’s dev Blog | Blur effects under iOS 7

Technical

Blur effects under iOS 7

by Katja

2014-04-24

Read more
let’s dev Blog | Beyond App Store - iOS application distribution

Technical

Beyond App Store - iOS application distribution

by Karl

2012-08-27

Read more
let’s dev Blog | Front-end architecture - Model View Presenter and Message Bus

Technical

Front-end architecture - Model View Presenter and Message Bus

by Karl

2011-03-08

Read more