Docs Menu
Docs Home
/ /
Atlas Device SDKs

Quick Start - C++ SDK

On this page

  • Import Realm
  • Define Your Object Model
  • Open a Realm
  • Create, Read, Update, and Delete Objects
  • Watch for Changes
  • Close a Realm
  • Add Device Sync (Optional)
  • Prerequisites
  • Initialize the App
  • Authenticate a User
  • Open a Realm
  • Read, Write, and React to Changes

This Quick Start demonstrates how to use Realm with the Realm C++ SDK. Before you begin, ensure you have Installed the C++ SDK.

Make the Realm C++ SDK available in your code by including the cpprealm/sdk.hpp header in the translation unit where you want to use it:

#include <cpprealm/sdk.hpp>

For a local-only realm you can define your object model directly in code. In this quick start, you can remove ownerId unless you want to add the optional Device Sync.

namespace realm {
struct Todo {
realm::primary_key<realm::object_id> _id{realm::object_id::generate()};
std::string name;
std::string status;
// The ownerId property stores the user.identifier() of a
// logged-in user. Omit this property for the non-sync example.
std::string ownerId;
REALM_SCHEMA(Todo, _id, name, status, ownerId);
} // namespace realm

When you open a realm, you must specify a db_config. You can optionally open a realm at a specific path, or provide a sync_config to open a synced realm.

auto config = realm::db_config();
auto realm = realm::db(std::move(config));

For more information, see: Configure and Open a Realm.

Once you have opened a realm, you can modify it and its objects in a write transaction block.

To instantiate a new Todo object and add it to the realm in a write block:

auto todo = realm::Todo{.name = "Create my first todo item",
.status = "In Progress"};
realm.write([&] { realm.add(std::move(todo)); });

You can retrieve a live results collection of all todos in the realm:

auto todos = realm.objects<realm::Todo>();

You can also filter that collection using where:

auto todosInProgress = todos.where(
[](auto const& todo) { return todo.status == "In Progress"; });

To modify a todo, update its properties in a write transaction block:

auto todoToUpdate = todosInProgress[0];
realm.write([&] { todoToUpdate.status = "Complete"; });

Finally, you can delete a todo:

realm.write([&] { realm.remove(specificTodo); });

You can watch an object for changes with the observe method.

auto token = specificTodo.observe([&](auto&& change) {
try {
if (change.error) {
if (change.is_deleted) {
std::cout << "The object was deleted.\n";
} else {
for (auto& propertyChange : change.property_changes) {
std::cout << "The object's " <<
<< " property has changed.\n";
} catch (std::exception const& e) {
std::cerr << "Error: " << e.what() << "\n";

To close a realm and release all underlying resources, call db::close(). Closing the database invalidates any remaining objects.


If you want to sync Realm data across devices, you can set up an Atlas App Services App and enable Device Sync. For more information on what you can do with App Services, see: Application Services - C++ SDK.

Before you can sync Realm data, you must:

To use App Services features such as authentication and sync, access your App Services App using your App ID. You can find your App ID in the App Services UI.

auto appConfig = realm::App::configuration();
appConfig.app_id = APP_ID;
auto app = realm::App(appConfig);

In this quick start, you use anonymous authentication to log in users without requiring them to provide any identifying information. After authenticating the user, you can open a realm for that user.

auto user = app.login(realm::App::credentials::anonymous()).get();

The Realm C++ SDK provides many additional ways to authenticate, register, and link users. For other authentication providers, see: Authenticate Users - C++ SDK

Once you have enabled Device Sync and authenticated a user, you can create a sync_configuration object and open the realm. You can then add a Flexible Sync subscription that determines what data the realm can read and write.

auto syncConfig = user.flexible_sync_configuration();
auto realm = realm::db(syncConfig);
// For this example, get the userId for the Flexible Sync query
auto userId = user.identifier();
auto subscriptions = realm.subscriptions();
auto updateSubscriptionSuccess =
.update([&](realm::mutable_sync_subscription_set& subs) {
subs.add<realm::Todo>("todos", [&userId](auto& obj) {
// For this example, get only Todo items where the ownerId
// property value is equal to the userId of the logged-in user.
return obj.ownerId == userId;

The syntax to read, write, and watch for changes on a synced realm is identical to the syntax for non-synced realms above.

The only difference here is that this example stores the user.identifier() of the logged-in user in the ownerId property of the Todo item. This lets us query for only the user's todos in the subscription, and set Sync permissions to Users can only read and write their own data.

For more information about Sync permissions, refer to Role-based Permissions.

auto todo = realm::Todo{.name = "Create a Sync todo item",
.status = "In Progress",
.ownerId = userId};
realm.write([&] { realm.add(std::move(todo)); });
auto todos = realm.objects<realm::Todo>();

While you work with local data, a background thread efficiently integrates, uploads, and downloads changesets.

Every write transaction for a subscription set has a performance cost. If you need to make multiple updates to a Realm object during a session, consider keeping edited objects in memory until all changes are complete. This improves sync performance by only writing the complete and updated object to your realm instead of every change.

← Install