C++ no desenvolvimento móvel: Android NDK, Unity e Unreal Engine

Autor: IT Sectr Publicado: 2026-02-10 Tempo de leitura: 11 min

C++ é uma linguagem de programação multiparadigma com gerenciamento manual de memória, combinando programação procedural, orientada a objetos e genérica. No desenvolvimento móvel, o C++ é usado através do Android NDK para portar bibliotecas e através dos motores de jogos Unity e Unreal Engine para criar jogos multiplataforma. De acordo com o TIOBE (2026), o C++ está entre as 5 linguagens mais populares entre desenvolvedores profissionais.

Pontos principais

  • C++ é uma linguagem de programação de sistemas usada no Android NDK, Unity e Unreal Engine
  • Android NDK permite compilar código C++ em bibliotecas nativas .so para processadores ARM
  • Unreal Engine é totalmente construído sobre C++, enquanto a Unity usa C++ para plugins de baixo nível
  • JNI (Java Native Interface) é a ponte entre Java/Kotlin e C++ no Android
  • CMake e NDK Build são sistemas de compilação para projetos C++ em plataformas móveis

O que é C++?

C++ é uma linguagem de programação criada por Bjarne Stroustrup em 1985 como uma extensão da linguagem C com suporte a classes. O C++ fornece acesso direto à memória através de ponteiros, metaprogramação de modelos e herança múltipla. Os padrões C++17 e C++20 adicionaram corrotinas, conceitos e ranges.

Ao contrário de Java e Kotlin, o C++ não possui coletor de lixo — o desenvolvedor gerencia manualmente a alocação e liberação de memória através dos operadores new e delete. Isso dá controle total sobre o desempenho, mas exige disciplina. De acordo com a JetBrains Developer Survey (2025), 42% dos desenvolvedores C++ usam a linguagem na indústria de jogos.

Os padrões C++ evoluem a cada três anos: C++11 (lambdas, auto, unique_ptr), C++14 (lambdas genéricas), C++17 (if constexpr, filesystem), C++20 (módulos, corrotinas, conceitos). Os compiladores Clang e GCC suportam todos os padrões atuais, e o Android NDK usa o Clang do toolchain LLVM.

Diferenças entre C++ e Java/Kotlin

A principal diferença entre C++ e as linguagens JVM é o gerenciamento manual de memória e a compilação direta para código de máquina. Java e Kotlin funcionam sobre uma máquina virtual com coleta automática de lixo. O código C++ compila em um binário nativo para uma arquitetura específica — ARM, x86 ou RISC-V.

CritérioC++Java / Kotlin
Gerenciamento de memóriaManual (new/delete, RAII)Automático (coletor de lixo)
CompilaçãoCódigo de máquina nativoBytecode JVM / ART
DesempenhoMáximo (abstrações de custo zero)Alto com pausas GC
Uso no desenvolvimento móvelNDK, jogos, bibliotecasAplicativos UI, lógica de negócios
CompilaçãoCMake, NDK Build, Gradle + NDKGradle, Maven
MultiplataformaCompilar para cada plataformaJVM / ART em toda parte

C++ no desenvolvimento móvel: Android NDK

Android NDK (Native Development Kit) é um kit de ferramentas do Google para escrever partes de aplicativos Android em C e C++. O NDK inclui um toolchain baseado em Clang, arquivos de cabeçalho do sistema Android e bibliotecas de depuração e perfilamento. A versão r27 (2025) suporta C++20 e usa LLVM 18.

O NDK compila código C++ em bibliotecas dinâmicas .so para as arquiteturas ARM64, ARM32, x86 e x86_64. Um aplicativo Java ou Kotlin carrega essas bibliotecas via System.loadLibrary() e chama funções nativas através do JNI. De acordo com o Google, o NDK foi baixado mais de 5 milhões de vezes.

Estrutura de projeto com NDK

Um projeto típico com Android NDK contém a pasta app/src/main/cpp/ com arquivos fonte C++, CMakeLists.txt para compilação e uma classe Java com declaração de métodos nativos. O Gradle conecta o NDK através do bloco externalNativeBuild no build.gradle.

cpp
// native-lib.cpp — método JNI simples para 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());
}

O código declara uma função JNI com o nome completo Java_com_example_app_MainActivity_stringFromJNI — esta é a convenção de nomenclatura JNI. A função recebe um ponteiro para JNIEnv (o ambiente de execução) e jobject (a instância da classe chamadora). env->NewStringUTF cria uma string Java a partir de uma string C++.

ABI e arquiteturas alvo

O Android suporta vários ABI (Application Binary Interface): arm64-v8a (dispositivos ARM de 64 bits, 99% dos smartphones modernos), armeabi-v7a (ARM de 32 bits, dispositivos antigos), x86_64 (emuladores). O NDK permite compilar .so para cada arquitetura através de filtros ABI no build.gradle.

gradle
android {
    defaultConfig {
        ndk {
            abiFilters "arm64-v8a", "armeabi-v7a"
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.22.1"
        }
    }
}

C++ e motores de jogos: Unity e Unreal Engine

C++ é a linguagem principal dos motores de jogos. O Unreal Engine usa C++ para todo o código do jogo, enquanto a Unity usa C++ no núcleo do motor para renderização e física. Mesmo se um desenvolvedor escrever em C# na Unity, internamente o C++ gerencia gráficos, som e cálculos físicos.

Unreal Engine: C++ como linguagem principal

O Unreal Engine é construído sobre C++ desde o início. O código da lógica do jogo é escrito em C++ usando macros UHT (Unreal Header Tool) para integração com Blueprints — um sistema de scripting visual. As classes herdam dos tipos base AActor, UObject, UGameInstance com letras de prefixo U, A, F.

cpp
// Classe de personagem no Unreal Engine usando 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;
};

As macros UCLASS() e UPROPERTY() fazem parte do sistema de reflexão do Unreal Engine. O UHT (Unreal Header Tool) gera código C++ a partir de arquivos de cabeçalho para serialização, blueprints e replicação de rede. MoveSpeed é exibido no editor via UPROPERTY(EditAnywhere).

Unity: C++ em plugins e SDK nativos

Unity usa C# para a lógica do jogo, mas C++ é usado em Native Plugins — bibliotecas .so para Android e .bundle para iOS. Através do Android NDK, é possível integrar SDKs C++ para redes de anúncios, análise ou portar bibliotecas C++ de jogos de desktop.

csharp
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);
    }
}

Neste exemplo, o C# faz marshaling de uma chamada para a função C++ ProcessFrame via P/Invoke. O atributo DllImport especifica o nome da biblioteca .so. A função C++ processa o quadro em tempo real e retorna o resultado. Esta abordagem é usada para pós-efeitos e visão computacional.

JNI: interação entre Java e C++

JNI (Java Native Interface) é o mecanismo padrão para chamar código C/C++ de Java ou Kotlin. No Android, JNI é a única maneira de transferir dados entre a máquina virtual ART e uma biblioteca nativa. Cada chamada JNI tem sobrecarga, portanto os dados devem ser transferidos em lotes em vez de um campo de cada vez.

JNIEnv é um ponteiro para a tabela de funções JNI. env->FindClass carrega uma classe Java, env->GetMethodID obtém um identificador de método, env->CallVoidMethod o invoca. Para strings, use GetStringUTFChars e ReleaseStringUTFChars. JNI também suporta referências globais e fracas para objetos Java.

cpp
// Passar array de bytes de C++ para Java via 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; // inverter bytes
    }

    env->ReleaseByteArrayElements(input, buffer, JNI_COMMIT);
}

GetByteArrayElements obtém um ponteiro para o array de bytes Java. JNI_COMMIT em ReleaseByteArrayElements copia as alterações de volta para o array Java sem liberar memória. O processamento do loop for é executado na CPU com máximo desempenho C++ sem pausas GC.

Gerenciamento de memória no JNI

O principal perigo do JNI são vazamentos de referências globais. Cada NewGlobalRef deve ser liberado via DeleteGlobalRef. Referências locais (retornadas por FindClass, NewStringUTF) são liberadas automaticamente ao retornar da função nativa. Para chamadas intensivas, use PushLocalFrame / PopLocalFrame.

CMake e sistemas de compilação para C++ no Android

CMake é a principal ferramenta de compilação para C++ no Android NDK. O CMakeLists.txt descreve os alvos de compilação, bibliotecas e dependências. O Gradle invoca o CMake através do externalNativeBuild, passando caminhos para o NDK e toolchain. Uma alternativa é o NDK Build baseado em Android.mk e Application.mk.

CMake 3.22+ suporta predefinições (CMakePresets.json) para diferentes configurações: debug, release, profile com diferentes flags de otimização. Para Android, usa-se o toolchain android.toolchain.cmake do NDK, fornecido automaticamente pelo Gradle durante a compilação.

cmake
# CMakeLists.txt para projeto 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) cria uma biblioteca .so. target_link_libraries vincula as bibliotecas do sistema android (para JNI) e log (para __android_log_print). A biblioteca estática libjpeg.a é vinculada para manipulação de imagens JPEG. CXX_STANDARD 20 ativa o suporte a C++20.

vcpkg e gerenciamento de dependências

vcpkg é um gerenciador de pacotes para C++ da Microsoft que suporta Android NDK como plataforma alvo. Através do vcpkg, é possível instalar Boost, OpenCV, SQLite, nlohmann-json e outras bibliotecas compiladas para Android ABI. O Vcpkg integra-se com CMake via CMAKE_TOOLCHAIN_FILE.

Desempenho do C++ em dispositivos móveis

C++ oferece desempenho máximo em dispositivos móveis graças à compilação em código ARM nativo e à ausência de coletor de lixo. De acordo com testes do Google (Android Performance Patterns, 2024), o código JNI em C++ executa 3–10 vezes mais rápido que o código Java equivalente para tarefas com cálculos intensivos.

Fatores-chave do desempenho do C++ em plataformas móveis: localidade de cache (disposição contígua de memória), instruções SIMD NEON para ARM, comunicação JNI assíncrona através de filas de mensagens. NEON é a extensão SIMD da ARM, processando 128 bits de dados em uma única instrução, indispensável para processamento de áudio, vídeo e imagens.

cpp
// Processamento SIMD de array via 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 carrega 4 floats da memória em um registrador NEON de 128 bits. vmulq_f32 multiplica todos os 4 elementos por 0.5 em um ciclo. vst1q_f32 armazena o resultado de volta. Sem SIMD, o mesmo loop executaria 4 multiplicações sequencialmente — o NEON oferece até 4x de aceleração para tais operações.

OperaçãoC++ (ms)Java/Kotlin (ms)Aceleração
Processamento de imagem 1920x108012453.75x
Transformada Rápida de Fourier (FFT)8344.25x
Criptografia AES-256 de bloco 1MB3186x
Compressão de dados ZLIB5224.4x

Erros comuns ao usar C++ em projetos móveis

O primeiro e mais perigoso erro são vazamentos de memória. Cada new deve ter um delete, cada new[] deve ter um delete[]. Em dispositivos móveis com RAM limitada, qualquer vazamento leva a OOM (Out Of Memory) e falha do aplicativo. Use RAII através de ponteiros inteligentes: std::unique_ptr, std::shared_ptr, std::weak_ptr.

O segundo erro é ignorar a compatibilidade ABI. Uma biblioteca compilada para armeabi-v7a não carregará em um dispositivo ARM64. Sempre especifique abiFilters no build.gradle e teste em dispositivos reais, não apenas no emulador x86_64. Use Android App Bundle para filtragem automática de ABI.

O terceiro erro típico são chamadas JNI frequentes. Cada transição entre Java e C++ custa cerca de 50–100 ns. Se você processar um array de 10000 elementos um por um via JNI, a sobrecarga excede o trabalho útil. Passe arrays inteiros de uma vez e processe-os no lado C++.

Problemas de threading são outro erro frequente. C++ pode iniciar std::thread, mas o JNI só pode ser acessado de threads criadas pelo Java. Para chamar métodos Java de uma thread C++, use AttachCurrentThread / DetachCurrentThread através do JNI.

cpp
// Chamar Java corretamente de uma thread C++
JavaVM *g_vm; // ponteiro global obtido no 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();
    }
}

Perguntas frequentes

O que é Android NDK e por que precisamos de C++ nele?

Android NDK (Native Development Kit) é um kit de ferramentas para escrever partes de aplicativos em C ou C++. É usado para tarefas críticas de desempenho, portar bibliotecas C/C++ para Android e implementar código multiplataforma para Unity e Unreal Engine.

Quais jogos da Unity são escritos em C++?

Na Unity, o código da lógica do jogo é escrito em C#, mas C++ é usado em conjunto com Android NDK para plugins, aceleração de hardware, portar bibliotecas C++ próprias e integrar SDKs nativos para publicidade e análise.

Como configurar CMakeLists.txt para C++ no Android?

CMakeLists.txt descreve arquivos fonte, bibliotecas e flags de compilação. A configuração mínima inclui add_library para compilar .so e target_link_libraries para vincular o log do Android e outras bibliotecas do sistema.

JNI em C++ é obrigatório para Android?

JNI (Java Native Interface) é a camada entre o código Java/Kotlin de um aplicativo Android e a biblioteca C++. Se C++ é chamado de Java, JNI é obrigatório. Você pode escrever código C++ inteiramente através do NDK, mas o ponto de entrada geralmente é uma Activity Java que chama funções nativas.

Quando o C++ é justificado em vez do Kotlin no desenvolvimento móvel?

C++ é justificado para jogos, processamento de áudio/vídeo em tempo real, visão computacional, criptografia, simulações físicas e portar bibliotecas de outras plataformas. Para um aplicativo UI comum, Kotlin é mais eficiente e simples.

Resumo

  • C++ é uma linguagem multiparadigma com gerenciamento manual de memória, usada no Android NDK, Unity e Unreal Engine para código de alto desempenho
  • Android NDK compila C++ em bibliotecas .so para arquiteturas ARM com o toolchain Clang do LLVM
  • Unreal Engine é totalmente construído sobre C++ com o sistema de reflexão UHT, Unity usa C++ em seu núcleo de renderização e física
  • JNI é a ponte obrigatória entre Java/Kotlin e C++ no Android com a convenção de nomenclatura Java___
  • CMake é o principal sistema de compilação para C++ no NDK, suportando C++20 e integração com Gradle
  • NEON SIMD fornece até 4x de aceleração no processamento de dados em processadores ARM através de instruções vetoriais de 128 bits
  • Erros comuns: vazamentos de memória, ABI incorreto em abiFilters, chamadas JNI frequentes e threading sem AttachCurrentThread

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também