C++ — un limbaj de programare multi-paradigmă cu gestionare manuală a memoriei, care combină programarea procedurală, orientată pe obiecte și generică. În dezvoltarea mobilă, C++ este utilizat prin Android NDK pentru portarea bibliotecilor și prin motoarele de jocuri Unity și Unreal Engine pentru crearea de jocuri cross-platform. Conform TIOBE (2026), C++ se află în top 5 limbaje după popularitate printre dezvoltatorii profesioniști.
Principalele puncte
C++ — un limbaj de programare creat de Bjarne Stroustrup în 1985 ca o extensie a limbajului C cu suport pentru clase. C++ oferă acces direct la memorie prin pointeri, meta-programare cu template-uri și moștenire multiplă. Standardele C++17 și C++20 au adăugat corutine, concepte și ranges.
Spre deosebire de Java și Kotlin, C++ nu are garbage collector — dezvoltatorul gestionează manual alocarea și eliberarea memoriei prin operatorii new și delete. Acest lucru oferă control complet asupra performanței, dar necesită disciplină. Conform JetBrains Developer Survey (2025), 42% dintre dezvoltatorii C++ folosesc limbajul în industria jocurilor.
Standardele C++ evoluează la fiecare trei ani: C++11 (lambda, auto, unique_ptr), C++14 (lambda generalizate), C++17 (if constexpr, filesystem), C++20 (module, corutine, concepte). Compilatoarele Clang și GCC suportă toate standardele actuale, iar pentru Android NDK se folosește Clang din toolchain-ul LLVM.
Principala diferență a C++ față de limbajele JVM — gestionarea manuală a memoriei și compilarea direct în cod mașină. Java și Kotlin rulează pe o mașină virtuală cu garbage collector automat. Codul C++ este compilat într-un fișier binar nativ pentru o arhitectură specifică — ARM, x86 sau RISC-V.
| Criteriu | C++ | Java / Kotlin |
|---|---|---|
| Gestionarea memoriei | Manuală (new/delete, RAII) | Automată (Garbage Collector) |
| Compilare | Cod mașină nativ | Bytecode JVM / ART |
| Performanță | Maximă (zero-cost abstractions) | Ridicată cu pauze GC |
| Utilizare în dezvoltarea mobilă | NDK, jocuri, biblioteci | Aplicații UI, logică de business |
| Build | CMake, NDK Build, Gradle + NDK | Gradle, Maven |
| Cross-platform | Compilare pentru fiecare platformă | JVM / ART peste tot |
Android NDK (Native Development Kit) — setul de instrumente Google pentru scrierea părților aplicației Android în C și C++. NDK include un toolchain bazat pe Clang, fișiere header de sistem Android, biblioteci pentru depanare și profilare. Versiunea r27 (2025) suportă C++20 și folosește LLVM 18.
NDK compilează codul C++ în biblioteci dinamice .so pentru arhitecturile ARM64, ARM32, x86 și x86_64. Aplicația Java sau Kotlin încarcă aceste biblioteci prin System.loadLibrary() și apelează funcțiile native prin JNI. Conform Google, NDK a fost descărcat de peste 5 milioane de ori.
Un proiect tipic cu Android NDK conține folderul app/src/main/cpp/ cu fișiere sursă C++, CMakeLists.txt pentru build și o clasă Java cu declararea metodelor native. Gradle conectează NDK prin blocul externalNativeBuild din build.gradle.
// native-lib.cpp — o metodă JNI simplă pentru Android
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_app_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /*thiz*/) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}Codul declară o funcție JNI cu numele complet Java_com_example_app_MainActivity_stringFromJNI — aceasta este convenția de denumire JNI. Funcția primește un pointer către JNIEnv (mediul de execuție) și jobject (instanța clasei apelante). env->NewStringUTF creează un șir Java dintr-un șir C++.
Android suportă mai multe ABI (Application Binary Interface): arm64-v8a (dispozitive ARM pe 64 de biți, 99% din smartphone-urile moderne), armeabi-v7a (ARM pe 32 de biți, dispozitive vechi), x86_64 (emulatoare). NDK permite build-ul .so pentru fiecare arhitectură prin filtre ABI în build.gradle.
android {
defaultConfig {
ndk {
abiFilters "arm64-v8a", "armeabi-v7a"
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.22.1"
}
}
}C++ — limbajul principal al motoarelor de jocuri. Unreal Engine folosește C++ pentru întreg codul jocului, iar Unity utilizează C++ în nucleul motorului pentru randare și fizică. Chiar dacă dezvoltatorul scrie în C# în Unity, sub capotă C++ gestionează grafica, sunetul și calculele fizice.
Unreal Engine este construit pe C++ de la zero. Codul logicii jocului se scrie în C++ cu ajutorul macro-urilor UHT (Unreal Header Tool) pentru integrarea cu Blueprints — sistemul vizual de scripting. Clasele moștenesc de la tipurile de bază AActor, UObject, UGameInstance cu literele prefix U, A, F.
// Clasa personajului în Unreal Engine în C++
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"
UCLASS()
class AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
AMyCharacter();
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere, Category = "Movement")
float MoveSpeed = 600.0f;
protected:
void SetupPlayerInputComponent(UInputComponent *PlayerInputComponent) override;
};Macro-urile UCLASS() și UPROPERTY() — fac parte din sistemul de reflecție al Unreal Engine. UHT (Unreal Header Tool) generează cod C++ din fișierele header pentru serializare, blueprinturi și replicare în rețea. MoveSpeed este afișat în editor prin UPROPERTY(EditAnywhere).
Unity folosește C# pentru logica jocului, dar C++ este utilizat în Native Plugins — biblioteci .so pentru Android și .bundle pentru iOS. Prin Android NDK se pot conecta SDK-uri C++ ale rețelelor de publicitate, analitică sau se poate porta o bibliotecă C++ din jocuri desktop.
using System.Runtime.InteropServices;
using UnityEngine;
public class NativeBridge : MonoBehaviour
{
const string LIB_NAME = "native_plugin";
[DllImport(LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int ProcessFrame(
int width, int height,
IntPtr pixelData
);
void Update()
{
int result = ProcessFrame(Screen.width, Screen.height, IntPtr.Zero);
Debug.Log("Frame processed: " + result);
}
}În acest exemplu, C# face marshalingul apelului către funcția C++ ProcessFrame prin P/Invoke. Atributul DllImport specifică numele bibliotecii .so. Funcția C++ procesează cadrul în timp real și returnează rezultatul. Această abordare este folosită pentru post-efecte și viziune computerizată.
JNI (Java Native Interface) — mecanismul standard pentru apelarea codului C/C++ din Java sau Kotlin. În Android, JNI este singura modalitate de a transmite date între mașina virtuală ART și biblioteca nativă. Fiecare apel JNI are un overhead, de aceea datele sunt transmise în pachete, nu câte un câmp.
JNIEnv — un pointer către tabela funcțiilor JNI. env->FindClass încarcă o clasă Java, env->GetMethodID obține identificatorul metodei, env->CallVoidMethod o apelează. Pentru șiruri se folosește GetStringUTFChars și ReleaseStringUTFChars. JNI suportă, de asemenea, referințe globale și slabe la obiecte Java.
// Transmiterea array-ului de bytes din C++ în Java prin JNI
extern "C" JNIEXPORT void JNICALL
Java_com_example_app_ImageProcessor_processArray(
JNIEnv *env, jobject /*thiz*/,
jbyteArray input, jint length) {
jbyte *buffer = env->GetByteArrayElements(input, nullptr);
jsize size = env->GetArrayLength(input);
for (jsize i = 0; i < size; ++i) {
buffer[i] = buffer[i] ^ 0xFF; // inversăm bytes
}
env->ReleaseByteArrayElements(input, buffer, JNI_COMMIT);
}GetByteArrayElements obține un pointer la array-ul de bytes Java. JNI_COMMIT în ReleaseByteArrayElements copiază modificările înapoi în array-ul Java fără a elibera memoria. Procesarea în buclă for se execută pe CPU cu performanța maximă a C++ fără pauze GC.
Principalul pericol al JNI — scurgeri de referințe globale. Fiecare NewGlobalRef trebuie eliberat prin DeleteGlobalRef. Referințele locale (returnate de FindClass, NewStringUTF) sunt șterse automat la revenirea din funcția native. Pentru apeluri intensive folosiți PushLocalFrame / PopLocalFrame.
CMake — instrumentul principal de build pentru C++ în Android NDK. CMakeLists.txt descrie țintele de build, bibliotecile și dependențele. Gradle apelează CMake prin externalNativeBuild, transmițând căile către NDK și toolchain. Alternativa — NDK Build bazat pe Android.mk și Application.mk.
CMake 3.22+ suportă preseturi (CMakePresets.json) pentru diferite configurații: debug, release, profile cu diferite flaguri de optimizare. Pentru Android se folosește toolchain-ul android.toolchain.cmake din NDK, substituit automat de Gradle la build.
# CMakeLists.txt pentru proiectul Android NDK
cmake_minimum_required(VERSION 3.22)
project("native-lib")
add_library(
native-lib
SHARED
src/main/cpp/native-lib.cpp
src/main/cpp/image_utils.cpp
)
target_include_directories(
native-lib PRIVATE
src/main/cpp/include
)
target_link_libraries(
native-lib
android
log
${CMAKE_SOURCE_DIR}/libs/libjpeg.a
)
set_target_properties(
native-lib PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
)add_library(SHARED) creează o bibliotecă .so. target_link_libraries conectează bibliotecile de sistem android (pentru JNI) și log (pentru __android_log_print). Biblioteca statică libjpeg.a este linkată pentru lucrul cu imagini JPEG. CXX_STANDARD 20 activează suportul C++20.
vcpkg — managerul de pachete pentru C++ de la Microsoft, care suportă Android NDK ca platformă țintă. Prin vcpkg se pot instala Boost, OpenCV, SQLite, nlohmann-json și alte biblioteci compilate pentru Android ABI. Vcpkg se integrează cu CMake prin CMAKE_TOOLCHAIN_FILE.
C++ oferă performanță maximă pe dispozitivele mobile datorită compilării în cod nativ ARM și absenței garbage collector-ului. Conform testelor Google (Android Performance Patterns, 2024), codul JNI în C++ se execută de 3–10 ori mai rapid decât codul Java echivalent pentru sarcini cu calcule intensive.
Factorii cheie ai performanței C++ pe platformele mobile: localitatea cache (plasarea datelor în memorie continuă), instrucțiunile SIMD NEON pentru ARM, lucrul asincron cu JNI prin cozi de mesaje. NEON — extensia SIMD a ARM, care permite procesarea a 128 de biți de date într-o singură instrucțiune, indispensabilă pentru procesarea audio, video și imagini.
// Procesarea SIMD a array-ului prin NEON intrinsics
#include <arm_neon.h>
void process_audio_neon(float *data, size_t n) {
for (size_t i = 0; i < n; i += 4) {
float32x4_t vec = vld1q_f32(&data[i]);
float32x4_t result = vmulq_f32(vec, vdupq_n_f32(0.5f));
vst1q_f32(&data[i], result);
}
}vld1q_f32 încarcă 4 float din memorie într-un registru NEON de 128 de biți. vmulq_f32 înmulțește toate cele 4 elemente cu 0.5 într-un singur ciclu. vst1q_f32 salvează rezultatul înapoi. Fără SIMD, aceeași buclă ar executa 4 înmulțiri secvențial — NEON oferă o accelerare de până la 4x pentru astfel de operații.
| Operație | C++ (ms) | Java/Kotlin (ms) | Accelerare |
|---|---|---|---|
| Procesarea imaginii 1920x1080 | 12 | 45 | 3.75x |
| Transformarea Fourier rapidă (FFT) | 8 | 34 | 4.25x |
| Criptarea AES-256 a unui bloc de 1MB | 3 | 18 | 6x |
| Comprimarea datelor ZLIB | 5 | 22 | 4.4x |
Prima și cea mai periculoasă greșeală — scurgerea de memorie. Fiecare new trebuie să aibă un delete, fiecare new[] — delete[]. Pe dispozitivele mobile cu RAM limitată, orice scurgere duce la OOM (Out Of Memory) și la căderea aplicației. Folosiți RAII prin pointeri inteligenți: std::unique_ptr, std::shared_ptr, std::weak_ptr.
A doua greșeală — ignorarea compatibilității ABI. O bibliotecă compilată pentru armeabi-v7a nu se va încărca pe un dispozitiv ARM64. Specificați întotdeauna abiFilters în build.gradle și testați pe dispozitive reale, nu doar pe emulatorul x86_64. Folosiți Android App Bundle pentru filtrarea automată ABI.
A treia greșeală tipică — apeluri frecvente JNI. Fiecare tranziție între Java și C++ costă aproximativ 50–100 ns. Dacă procesați un array de 10000 de elemente unul câte unul prin JNI, overhead-ul va depăși munca utilă. Transmiteți datele ca array-uri întregi și procesați-le pe partea C++.
Problemele cu multi-threading-ul — încă o greșeală frecventă. C++ poate porni std::thread, dar accesul la JNI este posibil doar din thread-ul creat de Java. Pentru a apela metode Java din thread-ul C++, folosiți AttachCurrentThread / DetachCurrentThread prin JNI.
// Apelarea corectă a Java din thread-ul C++
JavaVM *g_vm; // pointer global, obținut la JNI_OnLoad
void background_task() {
JNIEnv *env;
jint res = g_vm->AttachCurrentThread(&env, nullptr);
if (res == JNI_OK) {
jclass clazz = env->FindClass("com/example/App");
jmethodID mid = env->GetStaticMethodID(clazz, "onProgress", "(I)V");
env->CallStaticVoidMethod(clazz, mid, 100);
g_vm->DetachCurrentThread();
}
}Întrebări frecvente
Android NDK (Native Development Kit) — un set de instrumente pentru scrierea părților aplicației în C sau C++. Este utilizat pentru sarcini critice pentru performanță, portarea bibliotecilor C/C++ pe Android și implementarea codului cross-platform Unity și Unreal Engine.
În Unity, codul logicii jocului se scrie în C#, dar C++ este folosit împreună cu Android NDK pentru pluginuri, lucrul cu accelerarea hardware, portarea bibliotecilor proprii C++ și integrarea SDK-urilor native pentru publicitate și analitică.
CMakeLists.txt descrie fișierele sursă, bibliotecile și flagurile de compilare. Configurația minimă include add_library pentru build-ul .so și target_link_libraries pentru conectarea Android log și a altor biblioteci de sistem.
JNI (Java Native Interface) — stratul intermediar între codul Java/Kotlin al aplicației Android și biblioteca C++. Dacă C++ este apelat din Java, JNI este obligatoriu. Se poate scrie cod C++ complet prin NDK, dar punctul de intrare este de obicei o activitate Java care apelează funcții native.
C++ este justificat pentru jocuri, procesarea audio/video în timp real, viziune computerizată, criptografie, simulări fizice și portarea bibliotecilor de pe alte platforme. Pentru o aplicație UI obișnuită, Kotlin este mai eficient și mai simplu.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.