let’s dev GmbH & Co. KG - Die Marke für wegweisende Individualsoftware

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
1. April 2018

Smart Pointer in C++

Mit diesem Blogbeitrag soll ein Einblick in die Verwendung von Smart Pointern (Shared Pointern in C++) und die wichtigsten Grundlagen gegeben werden. Die nachfolgenden Erläuterungen zielen darauf ab, einen schnellen Einstieg in diese Thematik zu ermöglichen.

Einleitung

Im Einführungskapitel wird zunächst die Notwendigkeit von Shared Pointern verdeutlicht und zu deren Verwendung motiviert. Nicht ohne Grund sind Shared Pointer bei einigen höheren Programmiersprachen wie z.B. das ARC (Automatic Reference Counting) bei Objective-C ein Standard Sprach-Feature der Programmiersprache.

Smart Pointer in C++

Lesern, die bereits Grundkenntnisse besitzen und sich für ein lauffähiges Code Snippet interessieren, empfehlen wir, direkt bei Kapitel 2 Grundlagen der shared_ptr einzusteigen. Darin wird anhand von Beispielen die Verwendung der Shared Pointer erklärt.

Einführung - Das Mysterium der Shared Pointer in C++

“Warum kann man nicht einfach Shared Pointer verwenden? Shared Pointer sind eine sehr schlaue Methode zur Verwaltung von Pointern und des Speichers.”

Diese Aussage hört man sehr häufig. Aber werden Shared Pointer bereits wirklich im größeren Stil und konsequent in Projekten eingesetzt? Im Austausch mit Entwicklern gewinnt man schnell den Eindruck, dass Shared Pointer nicht besonders weit verbreitet oder populär sind. Woran liegt das? Gibt es Probleme, die bei der Verwendung häufiger auftreten? Sind Shared Pointer zu kompliziert zu verstehen oder ist es zu aufwendig, diese zu benutzen?

Wir hoffen, dass dieser Beitrag dabei helfen wird, einige der Fragen um das Mysterium Shared Pointer zu klären und ein gutes Beispiel dafür geben zu können, wie man diese korrekt verwendet.

Einführung - Eine Analogie zu Shared Pointern

Anstatt direkt in technische Details zu springen, wird die Verwendung von Shared Pointern zunächst anhand eines Beispiels aus dem echten Leben erläutert:

Stellen Sie sich vor, Sie arbeiten in einer Firma und es gibt eine einfache Regelung für das Bürogebäude: der letzte Mitarbeiter, welcher das Gebäude verlässt, muss die Eingangstür zum Gebäude verriegeln und die Alarmanlage aktivieren. Falls jemand das Gebäude verlässt und die Alarmanlage ist bereits aktiviert, dann wird der Alarm ausgelöst. Deswegen sollten Sie hier genau prüfen, ob sich noch jemand anderes im Gebäude befindet, bevor Sie die Alarmanlage aktiv schalten.

Angenommen, das Bürogebäude besteht nur aus einem kleinen Zimmer und es gibt nur fünf Mitarbeiter, dann ist es für Sie sehr einfach festzustellen, ob Sie der letzte Mitarbeiter sind, der sich noch im Gebäude befindet. Stellen Sie sich jedoch vor, Sie arbeiten in einem riesigen Bürogebäude mit mehreren Stockwerken und vielen hunderten Mitarbeitern. Um hier noch zu wissen, ob Sie die letzte Person im Gebäude sind, müssten Sie alle Stockwerke und alle Zimmer absuchen. Nun überlegen Sie sich, jemand anderes sucht zur gleichen Zeit das Gebäude ab, um nachzusehen, ob noch jemand anderes im Gebäude ist und sie beide verfehlen sich dadurch. Am Ende schließen Sie aus Versehen die andere Person im Gebäude ein, mit aktivierter Alarmanlage. Was für ein Chaos!

Aber was wäre, wenn es eine Art “Smart Door”, also eine Art “schlaue Eingangstür” zum Gebäude gäbe, welche +1 für jede Person addiert, die das Gebäude betritt und -1 subtrahiert für jede Person, die das Gebäude verlässt. Sobald der Zählerstand also den Wert 0 erreicht, wird die Alarmanlage automatisch aktiviert.

Wäre das nicht eine großartige Lösung für dieses Problem? Die Idee, welche sich hinter den Shared Pointern verbirgt, ähnelt der “Smart Door” aus dem erläuterten Beispiel.

Einführung - Die Verwendung von C++ shared_ptr

Bei der Programmierung in C++ ist es oft nicht einfach, den Überblick über die Speicherverwaltung des gesamten Source Codes eines Projektes zu behalten. Sobald ein C++ Pointer erzeugt wurde, kommen häufig folgende Fragen auf:

Als simple Antwort auf diese Fragen folgt dann meist folgende Aussage:

“Der Pointer wird an der Stelle im Programm gelöscht, in der er als letztes verwendet wurde.”

Aber wie in dem Beispiel aus 1.2, in dem nicht eindeutig bestimmt werden kann, wieviele Leute sich in einem großen Gebäude befinden, und wo genau diese sich aufhalten, so ist es keineswegs einfach, den Überblick darüber zu behalten, wohin alle Pointer in einem Programm weitergereicht wurden.

"Woher weiß man, welches die letzte Stelle ist, an der ein Pointer verwendet wurde?"

Ein Pointer könnte unter Umständen durch mehrere Konstruktoren oder Methoden Parameter weitergereicht worden sein. Außerdem könnte es sein, dass man mit mehreren Teamkollegen zusammen am selben Source Code arbeitet.

Vergleicht man die Behandlung von Pointern in C++ mit dem Beispiel aus 1.2, dann wäre ein Aufruf des delete Befehls auf einen Pointer, für welchen der Speicher bereits freigegeben wurde, gleichbedeutend mit dem Versuch, das Gebäude zu verlassen, in welchem bereits die Alarmanlage aktiviert wurde. Sobald man versucht, die Tür von innen zu öffnen, würde die Alarmanlage ausgelöst und bei den Pointern das Programm abstürzen.

Welches die letzte Stelle ist, an der ein Pointer verwendet wurde und zu wissen zu welchem Zeitpunkt man delete aufrufen sollte, ist keine Frage die sich so einfach beantworten lässt, sofern es eine dritte Instanz gibt, welche sich um diese Aufgabe kümmert. Und mit dieser dritten Instanz kommen Shared Pointer, wie der std::shared_ptr ins Spiel.

Der Shared Pointer weiß genau, welches die letzte Stelle ist, an der ein Pointer verwendet wurde und sobald ein Pointer zum letzten Mal im gesamten Programm verwendet wurde, wird er automatisch deleted. Hierfür addiert er +1. Dies geschieht jedes Mal, wenn jemand eine Kopie erzeugt, also z.B. wenn der Shared Pointer in einer Methode oder in einem Konstruktor als Parameter übergeben wird. Des Weiteren wird immer -1 subtrahiert, wenn das Objekt, welches den Shared Pointer verwendet hat, gelöscht oder die Methode, welche den Shared Pointer verwendet hat, beendet wurde. Sobald der Wert 0 erreicht wird, wird der Pointer automatisch gelöscht und der belegte Speicher wieder freigegeben.

Grundlagen der shared_ptr

Nachfolgend werden nun einige Code Beispiele präsentiert. Aufgrund der Anschaulichkeit wird auch hier nochmal das Büro Beispiel aus Kapitel 1.2 aufgegriffen:

Es wird zunächst eine Klasse OfficeBuilding definiert, also ein Gebäude, welches von Mitarbeitern betreten werden kann. Das bedeutet, ein OfficeBuilding kann mehrere Instanzen eines Mitarbeiter Objektes (Employee) referenzieren. Und als kleines, zusätzliches Feature gibt es in dem Gebäude ein WC (Washroom), welches von genau einem Mitarbeiter betreten werden kann.

Datenbankrelationen

Grundlagen der shared_ptr - Instanziierung eines shared_ptr

Möchte man z.B. eine Instanz eines Objektes Employee erzeugen, dann würde man normalerweise einen Pointer mit Hilfe des Schlüsselworts new instanziieren, um Heap-Speicher zu allokieren. Das Schlüsselwort delete würde man dazu verwenden, um den Speicher wieder freizugeben:

Employee  *employee1 = new Employee( 1, “Peter Parker”);
delete employee1;
Diese beiden Zeilen Code werden nun ersetzt durch die Folgende:
shared_ptr<Employee> employee1 = make_shared<Employee>(1, "Peter Parker");

Die linke Seite der Zuweisung shared_ptr<Employee> employee1 hält sich eine Instanz der Klasse Employee und anstatt das Schlüsselwort new zu verwenden, verwendet man das Schlüsselwort make_shared, um diese Instanz zu erzeugen.

Die Parameter, welche man normalerweise dem Konstruktor der Klasse Employee übergeben würde, werden stattdessen dem Ausdruck shared_ptr<Employee> (parameter1, parameter2, ...) übergeben.

Sobald der aktuelle Kontext verlassen wird, also z.B. der Kontext der momentan aufgerufenen Methode, wird der Speicher, welcher von der employee1 Instanz belegt wurde, automatisch freigegeben. Der Aufruf des delete-Befehls ist somit nicht notwendig.

Grundlagen der shared_ptr - Zugriff auf Class Members eines Shared Pointers

Angenommen, man möchte unter Verwendung der Getter Methode auf den Namen der Variablen employee1 zugreifen, dann könnte man dies tun, indem man die Variable wie einen ganz normalen C++ Pointer behandelt und den Pfeil Operator “->” verwendet:

string employeeName = employee1->getName();

Die Verwendung des Punkt Operators “.” gewährt im Gegensatz dazu den Zugriff auf hilfreiche Informationen über die shared reference wie zum Beispiel die Anzahl an Reference Counts:

long employee1UseCount = employee1.use_count();

Theoretisch betrachtet, ist es möglich, über den Shared Pointer auch noch auf den Raw Pointer zuzugreifen, welcher vom Shared Pointer verwaltet wird:

Employee *pointer = employee1.get();

Jedoch sollte ein Zugriff auf den Raw Pointer, wie in diesem Beispiel um jeden Preis vermieden werden, weil dies wieder nur zu altbekannten Problemen führt: jemand versucht, Speicher freizugeben, welcher bereits freigegeben wurde. Diese Möglichkeit soll hier nur aus Gründen der Vollständigkeit erwähnt werden.

Grundlagen der shared_ptr - Kopieren eines shared_ptr

Wie kann man eine Kopie eines shared_ptr machen, welcher auf allokierten Speicher verweist? Vergleicht man es mit normalen Pointern, dann würde man normalerweise Folgendes schreiben:

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

Die erste Zeile des Codes allokiert ein Employee Objekt und lässt den Pointer employee1 auf den neu allokierten Speicher zeigen. Anschließend wird in der zweiten Zeile eine Kopie dieser Variable gemacht und die neue Variable employee1Copy verweist dann auf denselben Speicherbereich wie employee1. Wenn man etwas vergleichbares mit einem shared_ptr machen möchte, dann gibt es zwei Möglichkeiten:


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

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

Wie verhält sich das Reference Counting?

Nachdem nun die Grundlagen über shared_ptr vermittelt wurden, wäre es als nächstes interessant, zu betrachten, wie sich das Reference Counting in einem richtigen Code Beispiel verhält.

Zunächst soll die Klasse Employee betrachtet werden. Ein Mitarbeiter (Employee) hat ein Attribut Name und eine eindeutige Id, welche dem Konstruktor übergeben werden kann. Diese Klasse enthält, um das Beispiel möglichst einfach zu halten, keine Pointer oder Shared Pointer.

#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

Um einen besseren Überblick über die Reference Counts zu haben, gibt es noch eine Methode printCurrentUseCount. Da bei jedem Aufruf der Methode ein neuer Kontext betreten wird und damit das Ergebnis um den Wert +1 “verfälscht” würde, wird hier wieder das auszugebende Ergebnis immer um -1 heruntergesetzt.

Das OfficeBuilding, in welchem die Mitarbeiter arbeiten, kann durch den Aufruf der Method enterBuilding und leaveBuilding von Mitarbeitern betreten bzw. verlassen werden. Bei genauerem Hinsehen fällt auf, dass die Klasse OfficeBuilding eine Klassenvariable vector<shared_ptr<Employee>> smartDoorPeopleCounter hat, welche sich merkt, welche Mitarbeiter sich zur Zeit im Gebäude befinden.

Über die beiden Methoden useWashRoom und leaveWashRoom kann immer genau ein Mitarbeiter das WC betreten bzw. wieder verlassen.

#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

Das Objekt Washroom hält sich immer einen shared_ptr auf den aktuellen Mitarbeiter, welcher gerade das WC benutzt.

#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

Der folgende Beispielcode allokiert einige Mitarbeiter Objekte (Employee) und lässt diese das OfficeBuilding betreten und wieder verlassen.


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;

Die Print-Ausgaben sollen hier verdeutlichen, wie jeweils der aktuelle Reference Count ist:

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

Die Verwendung von shared_ptr innerhalb von Threads

Es wird vermutet, dass es bei der Verwendung von C++ Shared Pointern zu Problemen im Zusammenhang mit Threads kommen könnte. Nachfolgend auch ein Beispiel für diesen speziellen Fall: es gibt ein Cafe, welches sich außerhalb des Gebäudes OfficeBuilding befindet und welches ein Mitarbeiter (Employee) besuchen kann.

Das Cafe kann mittels der Methode visitCoffeeHouse betreten werden. In dieser Methode wird zunächst der Shared Pointer auf den Mitarbeiter einer auto Variable zugewiesen und anschließend einem Shared Pointer struct, welcher als Container für die Parameter des Threads dient.


#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

Der Thread wird innerhalb eines speziellen Kontextes gestartet, wobei der Kontext durch die geschweiften Klammern { } markiert ist. Innerhalb des Kontextes wird der useCount den Wert 5 haben, kurz bevor der Thread gestartet wird. Nachdem der Thread gestartet wurde, wird der Kontext verlassen, während der Thread für 5 Sekunden schläft und in der Zwischenzeit wird der Reference Count durch den Main Thread auf den Wert 4 verringert.

Sobald der Thread wieder erwacht, wird dieser eine lokale und eine globale Kopie des Shared Pointer machen, was zu der Ausgabe des Wertes 6 führt.

Nachdem der Thread beendet wurde, verbleibt lediglich die globale Kopie, was zu einer Ausgabe des Wertes 5 führt. Das Endergebnis nach dem Verlassen der Methode visitCoffeeHouse für den Mitarbeiter “Peter Parker” ist der Wert 4.

Auf den ersten Blick sieht mit den Threads alles relativ normal aus. Das heißt, die reference counts scheinen korrekt erhöht und verringert zu werden. Jedoch können Probleme nie völlig ausgeschlossen werden. Möchte man ganz sicher gehen, empfiehlt es sich, nur auf einer Kopie der Daten zu arbeiten.

Zusammenfassung

Das Konzept der C++ shared_ptr bietet eine Alternative zu den traditionellen C++ Pointern. Es ist jedoch entscheidend, niemals normale C++ Pointer und Shared Pointer zu vermischen, weil dies zu ernsthaften Problemen führen kann.

Der große Vorteil der Shared Pointer, die automatische Verwaltung von Speicher-Referenzen, ersetzt außerdem die mühselige, manuelle Speicherfreigabe. Des Weiteren wurde ein Einblick gegeben, wie sich das Reference Counting verhält. Einfach gesagt: Wann immer ein neuer Kontext betreten wird z.B. eine Methode oder eine Kopie eines Shared Pointers, wird der Reference Count um +1 erhöht. Sobald ein Kontext wieder verlassen wird, wird der Reference Count automatisch verringert, abhängig von der Anzahl der Kopien in diesem Kontext. Nach intensiver Einarbeitung in die Thematik, lässt sich festhalten, dass Shared Pointer den Entwicklungsprozess deutlich komfortabler und einfacher machen können. Auch die Kollaboration mit Teamkollegen wird durch diese deutlich erleichtert. Es dürfte spannend werden, Shared Pointer zukünftig auch in größeren Projekten einzusetzen.

Einen kleinen Nachteil könnte es dabei jedoch geben: sofern man Shared Pointer in einem Projekt verwendet und im selben Projekt auch eine externe Bibliothek wie z.B. OpenCV verwenden möchte, welche vielleicht in den Interfaces keine Shared Pointer anbietet, sollte man sehr vorsichtig damit umgehen. Möglicherweise bietet es sich an, hier dann eine “tiefe Kopie” der Daten zu verwenden, welche man als Parameter den Schnittstellen der Bibliothek übergeben möchte.

Bildnachweis:

  • iStock: kasto80

Weitere Artikel aus unserem Blog

let’s dev Blog | Designing for a Better World – Der World Usability Day in Stuttgart

Corporate

Designing for a Better World – Der World Usability Day in Stuttgart

by Julia & Nadine

2024-11-19

Weiterlesen
let’s dev Blog | Sustainable UX Design (SUX)

Technical

Sustainable UX Design (SUX)

by Nadine B.

2024-10-30

Weiterlesen
let’s dev Blog | KI, Leistungsverbesserungen und mehr Datenschutz: Das Android 15 Update

Technical

KI, Leistungsverbesserungen und mehr Datenschutz: Das Android 15 Update

by Julian

2024-10-09

Weiterlesen
let’s dev Blog | Wichtige Barrierefreiheitsstandards für Webseiten ab 2025

Technical

Wichtige Barrierefreiheitsstandards für Webseiten ab 2025

by Nadine

2024-08-06

Weiterlesen
let’s dev Blog | Automatisierte Arbeitsabläufe: Maximale Produktivität dank Zapier

Technical

Automatisierte Arbeitsabläufe: Maximale Produktivität dank Zapier

by Antonia

2024-07-18

Weiterlesen
let’s dev Blog | Apple Intelligence und ChatGPT: Die Highlights der WWDC24

Technical

Apple Intelligence und ChatGPT: Die Highlights der WWDC24

by Julian

2024-06-13

Weiterlesen
let’s dev Blog | Groß, größer, OMR: let’s dev und Kortpress auf dem OMR Festival 2024

Corporate

Groß, größer, OMR: let’s dev und Kortpress auf dem OMR Festival 2024

by Julian

2024-05-24

Weiterlesen
let’s dev Blog | Entdecke die Dynamic Island: Eine weitere Innovation der iOS-Welt

Technical

Entdecke die Dynamic Island: Eine weitere Innovation der iOS-Welt

by Nico

2024-04-05

Weiterlesen
let’s dev Blog | Der World Usability Day 2023

Corporate

Der World Usability Day 2023

by Sina

2023-11-10

Weiterlesen
let’s dev Blog | Adobe Max 2023

Corporate

Adobe Max 2023

by Julia

2023-10-13

Weiterlesen
let’s dev Blog | Barrierefreiheit in der Webentwicklung

Technical

Barrierefreiheit in der Webentwicklung

by Sarah

2023-10-31

Weiterlesen
let’s dev Blog | Digitale Wallet-Karten: Stärkung von Kundenbindung im digitalen Zeitalter

Corporate

Digitale Wallet-Karten: Stärkung von Kundenbindung im digitalen Zeitalter

by Julian

2023-07-07

Weiterlesen
let’s dev Blog | Kortpress auf dem OMR Festival 2023 in Hamburg

Corporate

Kortpress auf dem OMR Festival 2023 in Hamburg

by Julian

2023-05-31

Weiterlesen
let’s dev Blog | Recap 2022: Smart Devices, digitale Plattformen und innovative Forschungsprojekte

Corporate

Recap 2022: Smart Devices, digitale Plattformen und innovative Forschungsprojekte

by Julian

2023-01-31

Weiterlesen
let’s dev Blog | Mit LottieFiles Animationen für das Web erstellen

Corporate

Mit LottieFiles Animationen für das Web erstellen

by Julian

2022-12-15

Weiterlesen
let’s dev Blog | Lean in der Softwareentwicklung

Technical

Lean in der Softwareentwicklung

by Sabrina

2022-12-08

Weiterlesen
let’s dev Blog | Adobe Max - Live aus LA

Corporate

Adobe Max - Live aus LA

by Jessica

2022-10-28

Weiterlesen
let’s dev Blog | Mensch und Computer 2022 - Facing Realities

Corporate

Mensch und Computer 2022 - Facing Realities

by Kerstin

2022-09-12

Weiterlesen
let’s dev Blog | EUREKA Innovation Award

Corporate

EUREKA Innovation Award

by Karl

2022-06-23

Weiterlesen
let’s dev Blog | Die WWDC 2022: Unser Update zu Apples neuen Betriebssystemen

Technical

Die WWDC 2022: Unser Update zu Apples neuen Betriebssystemen

by Julian

2022-06-08

Weiterlesen
let’s dev Blog | Docker und die versteckte Sicherheitslücke

Technical

Docker und die versteckte Sicherheitslücke

by Martin

2022-02-17

Weiterlesen
let’s dev Blog | Die Weihnachtsfeiertage stehen wieder vor der Tür – Wir blicken gespannt auf das nächste Jahr 2022!

Corporate

Die Weihnachtsfeiertage stehen wieder vor der Tür – Wir blicken gespannt auf das nächste Jahr 2022!

by Julian

2021-12-22

Weiterlesen
let’s dev Blog | Fertigung und Montage von Stacks und Elektro­lyseuren für die Wasser­stoff­herstellung

Corporate

Fertigung und Montage von Stacks und Elektro­lyseuren für die Wasser­stoff­herstellung

by Anton

2021-12-21

Weiterlesen
let’s dev Blog | Adobe Max 2021 - Ein Fest der Kreativität

Corporate

Adobe Max 2021 - Ein Fest der Kreativität

by Julia

2021-11-02

Weiterlesen
let’s dev Blog | Relationale Datenbanken im Vergleich zu objektorientierten Datenbanken

Technical

Relationale Datenbanken im Vergleich zu objektorientierten Datenbanken

by Julian

2021-10-14

Weiterlesen
let’s dev Blog | Apple Developer Program: Wofür wird es benötigt und welche Inhalte bieten mir eine Mitgliedschaft?

Corporate

Apple Developer Program: Wofür wird es benötigt und welche Inhalte bieten mir eine Mitgliedschaft?

by Julian

2021-09-30

Weiterlesen
let’s dev Blog | Sketch, Figma & Co - Wir werfen einen Blick auf die beliebtesten UI und Prototyping Tools 2021

Corporate

Sketch, Figma & Co - Wir werfen einen Blick auf die beliebtesten UI und Prototyping Tools 2021

by Ellen

2021-07-15

Weiterlesen
let’s dev Blog | Rückenwind: Ein innovatives Projekt für den Weiterbetrieb von alten Windkraftanlagen

Corporate

Rückenwind: Ein innovatives Projekt für den Weiterbetrieb von alten Windkraftanlagen

by Karl

2021-06-24

Weiterlesen
let’s dev Blog | Features, Fixes und Funktionen - Ein Sumup der WWDC 2021

Corporate

Features, Fixes und Funktionen - Ein Sumup der WWDC 2021

by Julian

2021-06-10

Weiterlesen
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

Weiterlesen
let’s dev Blog | Dasoman - Daten-Souveränitäts-Manager

Corporate

Dasoman - Daten-Souveränitäts-Manager

by Karl

2021-01-11

Weiterlesen
let’s dev Blog | Wir blicken auf die vergangenen Monate zurück – Und wünschen alles Gute für das kommende Jahr 2021!

Corporate

Wir blicken auf die vergangenen Monate zurück – Und wünschen alles Gute für das kommende Jahr 2021!

by Julian

2020-12-17

Weiterlesen
let’s dev Blog | iOS User Interface Tests

Technical

iOS User Interface Tests

by Nicolas

2020-11-12

Weiterlesen
let’s dev Blog | Adobe Max - Zum ersten Mal online

Corporate

Adobe Max - Zum ersten Mal online

by Julia

2020-10-29

Weiterlesen
let’s dev Blog | CAN2BLE

Technical

CAN2BLE

by Raphael

2020-09-24

Weiterlesen
let’s dev Blog | Mensch und Computer 2020 - Digitaler Wandel im Fluss der Zeit

Corporate

Mensch und Computer 2020 - Digitaler Wandel im Fluss der Zeit

by UX Team

2020-09-18

Weiterlesen
let’s dev Blog | Neumorphism – Eine neue Ära des User Interface Design?

Technical

Neumorphism – Eine neue Ära des User Interface Design?

by Julian

2020-08-13

Weiterlesen
let’s dev Blog | UX-Research Teil 3 – UX Methoden

Technical

UX-Research Teil 3 – UX Methoden

by Elena

2020-05-28

Weiterlesen
let’s dev Blog | UX-Research Teil 2 - Was ist UCD und was hat User Research damit zu tun?

Technical

UX-Research Teil 2 - Was ist UCD und was hat User Research damit zu tun?

by Elena

2020-04-23

Weiterlesen
let’s dev Blog | go-digital fördert Einrichtung von Home Office Arbeitsplätzen

Corporate

go-digital fördert Einrichtung von Home Office Arbeitsplätzen

by Karl

2020-03-19

Weiterlesen
let’s dev Blog | Google Passes - Karten­verwaltung auf  Android-Geräten

Technical

Google Passes - Karten­verwaltung auf Android-Geräten

by Michelle

2020-03-12

Weiterlesen
let’s dev Blog | 100% Code-Coverage bei Software Tests – eine sinnvolle Zielsetzung?

Technical

100% Code-Coverage bei Software Tests – eine sinnvolle Zielsetzung?

by Raphael

2020-03-06

Weiterlesen
let’s dev Blog | Swift UI - Einfache und schnelle Umsetzung von User Interfaces

Technical

Swift UI - Einfache und schnelle Umsetzung von User Interfaces

by Tobias

2020-03-02

Weiterlesen
let’s dev Blog | Im Dialog mit den Wirtschafts­junioren – Spannende Einblicke in die Unternehmens­gründung und die digitale Trans­formation

Corporate

Im Dialog mit den Wirtschafts­junioren – Spannende Einblicke in die Unternehmens­gründung und die digitale Trans­formation

by Julian

2020-02-27

Weiterlesen
let’s dev Blog | Vereinfachtes Testen von iOS Push Notifications im Simulator mit Xcode 11.4

Technical

Vereinfachtes Testen von iOS Push Notifications im Simulator mit Xcode 11.4

by Manuel

2020-02-26

Weiterlesen
let’s dev Blog | Nationales Meeting des Konsortiums des SPEAR Forschungs­projektes bei let’s dev in Karlsruhe

Corporate

Nationales Meeting des Konsortiums des SPEAR Forschungs­projektes bei let’s dev in Karlsruhe

by Karl

2020-01-27

Weiterlesen
let’s dev Blog | UX-Research Teil 1 – Warum User Research so wichtig ist

Technical

UX-Research Teil 1 – Warum User Research so wichtig ist

by Elena

2020-01-23

Weiterlesen
let’s dev Blog | Dark Mode

Technical

Dark Mode

by Elisa

2020-01-09

Weiterlesen
let’s dev Blog | Wir wünschen frohe Weihnachten – Und einen guten Start ins neue Jahr!

Corporate

Wir wünschen frohe Weihnachten – Und einen guten Start ins neue Jahr!

by Julian

2019-12-20

Weiterlesen
let’s dev Blog | Austausch zum Thema Digitalisierung mit dem Business Club Luxemburg in der Botschaft von Luxemburg in Berlin

Corporate

Austausch zum Thema Digitalisierung mit dem Business Club Luxemburg in der Botschaft von Luxemburg in Berlin

by Karl

2019-12-17

Weiterlesen
let’s dev Blog | DaSoMan auf der Internet+ Expo in Foshan (China)

Corporate

DaSoMan auf der Internet+ Expo in Foshan (China)

by Karl

2019-12-13

Weiterlesen
let’s dev Blog | Google Play Console: Pre-Launch Berichte

Technical

Google Play Console: Pre-Launch Berichte

by Fabian

2019-12-11

Weiterlesen
let’s dev Blog | DevFest 2019 in Hamburg

Technical

DevFest 2019 in Hamburg

by Julian

2019-12-05

Weiterlesen
let’s dev Blog | Vernissage digitale Kunst im Medientheater der Humboldt Universität Berlin

Corporate

Vernissage digitale Kunst im Medientheater der Humboldt Universität Berlin

by Karl

2019-11-21

Weiterlesen
let’s dev Blog | World Usability Day 2019 in Karlsruhe – let’s dev unterstützt als Hauptsponsor

Corporate

World Usability Day 2019 in Karlsruhe – let’s dev unterstützt als Hauptsponsor

by Aileen

2019-11-11

Weiterlesen
let’s dev Blog | Ausgeschlachtet - Tag der offenen Türen auf dem Alten Schlachthof Karlsruhe 2019

Corporate

Ausgeschlachtet - Tag der offenen Türen auf dem Alten Schlachthof Karlsruhe 2019

by Julian

2019-09-26

Weiterlesen
let’s dev Blog | Mensch und Computer 2019 - Konferenz zu User Experience und Usability in Hamburg

Corporate

Mensch und Computer 2019 - Konferenz zu User Experience und Usability in Hamburg

by Elena

2019-09-17

Weiterlesen
let’s dev Blog | Business und Enterprise App Verteilung unter iOS

Technical

Business und Enterprise App Verteilung unter iOS

by Aileen

2019-08-05

Weiterlesen
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

Weiterlesen
let’s dev Blog | let’s dev unterstützt Läuferinnen und Läufer bei der 7. KIT Meisterschaft

Corporate

let’s dev unterstützt Läuferinnen und Läufer bei der 7. KIT Meisterschaft

by Karl

2019-07-05

Weiterlesen
let’s dev Blog | Automatisiertes Testing von C++ Code mit Google Test und Google Mock – Teil 2

Technical

Automatisiertes Testing von C++ Code mit Google Test und Google Mock – Teil 2

by Arne

2019-06-13

Weiterlesen
let’s dev Blog | Apple WWDC 2019: Das sind die Highlights der Keynote

Technical

Apple WWDC 2019: Das sind die Highlights der Keynote

by Nicolas

2019-06-05

Weiterlesen
let’s dev Blog | App Builders 2019

Technical

App Builders 2019

by Nicolas

2019-05-23

Weiterlesen
let’s dev Blog | Offizielle Eröffnung des Festigungs- und Expansionszentrums (FUX)

Corporate

Offizielle Eröffnung des Festigungs- und Expansionszentrums (FUX)

by Helena

2019-04-15

Weiterlesen
let’s dev Blog | Delegation aus Nottingham zu Besuch auf dem Alten Schlachthof in Karlsruhe

Corporate

Delegation aus Nottingham zu Besuch auf dem Alten Schlachthof in Karlsruhe

by Helena

2019-04-14

Weiterlesen
let’s dev Blog | Es ist soweit: Wir ziehen um!

Corporate

Es ist soweit: Wir ziehen um!

by Helena

2019-03-26

Weiterlesen
let’s dev Blog | Automatisiertes Testing von C++ Code mit Frameworks – Teil 1

Technical

Automatisiertes Testing von C++ Code mit Frameworks – Teil 1

by Arne

2019-02-20

Weiterlesen
let’s dev Blog | Die App im Google Play Store

Technical

Die App im Google Play Store

by Elisa

2019-01-24

Weiterlesen
let’s dev Blog | „UX Day“ 2018

Corporate

„UX Day“ 2018

by Aileen

2018-12-17

Weiterlesen
let’s dev Blog | let’s dev unterstützt SG Siemens Volleyballer aus Karlsruhe

Corporate

let’s dev unterstützt SG Siemens Volleyballer aus Karlsruhe

by Helena

2018-12-04

Weiterlesen
let’s dev Blog | KMU gestalten die Digitalisierung – Mittelstandskonferenz 2018

Corporate

KMU gestalten die Digitalisierung – Mittelstandskonferenz 2018

by Helena

2018-11-12

Weiterlesen
let’s dev Blog | Apple Wallet

Technical

Apple Wallet

by Maik

2018-10-26

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

Corporate

„Mensch und Computer“ 2018

by Judith

2018-09-24

Weiterlesen
let’s dev Blog | State Design Pattern in Android

Technical

State Design Pattern in Android

by Thomas

2018-09-17

Weiterlesen
let’s dev Blog | let’s dev ist autorisiertes Beraterunternehmen im Förderprogramm „go-digital“

Corporate

let’s dev ist autorisiertes Beraterunternehmen im Förderprogramm „go-digital“

by Helena

2018-09-01

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

Corporate

App Design & Development Conference 2018

by Helena

2018-08-14

Weiterlesen
let’s dev Blog | iOS 12: Die Top-Neuerungen im Überblick

Technical

iOS 12: Die Top-Neuerungen im Überblick

by Nicolas

2018-07-17

Weiterlesen
let’s dev Blog | let’s dev auf der CEBIT

Corporate

let’s dev auf der CEBIT

by Karl

2018-06-11

Weiterlesen
let’s dev Blog | Einführung in User Interface (UI) Tests mit Espresso

Technical

Einführung in User Interface (UI) Tests mit Espresso

by Raphael

2018-06-07

Weiterlesen
let’s dev Blog | Die App im Apple App Store: welche Informationen werden benötigt?

Technical

Die App im Apple App Store: welche Informationen werden benötigt?

by Aileen

2018-04-27

Weiterlesen
let’s dev Blog | User Interface Design für das iPhone X: alle Neuerungen auf einen Blick

Technical

User Interface Design für das iPhone X: alle Neuerungen auf einen Blick

by Helena

2018-02-07

Weiterlesen
let’s dev Blog | WebVR – Virtual Reality Experience im Browser mit dem A-Frame Framework

Technical

WebVR – Virtual Reality Experience im Browser mit dem A-Frame Framework

by Judith

2018-01-10

Weiterlesen
let’s dev Blog | Open Data Hackathon der Deutschen Bahn

Corporate

Open Data Hackathon der Deutschen Bahn

by Karl

2015-03-31

Weiterlesen
let’s dev Blog | Blur-Effekte unter iOS 7

Technical

Blur-Effekte unter iOS 7

by Katja

2014-04-24

Weiterlesen
let’s dev Blog | Beyond App Store – Distribution von iOS-Anwendungen

Technical

Beyond App Store – Distribution von iOS-Anwendungen

by Karl

2012-08-27

Weiterlesen
let’s dev Blog | Frontend-Architektur – Model View Presenter und Message Bus

Technical

Frontend-Architektur – Model View Presenter und Message Bus

by Karl

2011-03-08

Weiterlesen