Memory Ownership and Smart Pointers

Unique Pointers with C-style APIs

Can I use unique pointers with C-style APIs that expect raw pointers?

Abstract art representing computer programming

Yes, you can use std::unique_ptr with C-style APIs that expect raw pointers. This is actually one of the strengths of smart pointers - they can seamlessly integrate with existing code that uses raw pointers. However, there are a few things to keep in mind when doing so.

Using get() for Read-Only Access

When you need to pass the raw pointer to a function that doesn't take ownership (i.e., doesn't delete the pointer), you can use the get() member function of std::unique_ptr. This returns the underlying raw pointer without affecting ownership.

#include <memory>
#include <iostream>

class Character {
public:
  std::string Name;
};

// A C-style function that expects a raw pointer
void PrintCharacterName(const Character* Char) {
  std::cout << "Character name: " << Char->Name << '\n';
}

int main() {
  auto Legolas{std::make_unique<Character>("Legolas")};
  PrintCharacterName(Legolas.get()); 
}
Character name: Legolas

Passing to Functions That Take Ownership

If you need to pass your unique_ptr to a function that takes ownership (i.e., it's responsible for deleting the pointer), you should use the release() method to cause the unique pointer to give up ownership:

#include <memory>
#include <iostream>

class Character {
public:
  std::string Name;
};

// A function that takes ownership of the pointer
void TakeOwnershipOfCharacter(Character* Char) {
  // Do something with Char
  delete Char;
}

int main() {
  auto Gimli{std::make_unique<Character>("Gimli")};
  TakeOwnershipOfCharacter(Gimli.release()); 
  // Gimli is now nullptr
}

Receiving Raw Pointers from C-style APIs

When receiving a raw pointer from a C-style API, you can wrap it in a unique_ptr:

#include <memory>
#include <string>

class Character {
public:
  std::string Name;
};

// A C-style function that returns a raw pointer
Character* CreateCharacter(const char* Name) {
  return new Character(Name);
}

int main() {
  std::unique_ptr<Character> Aragorn{ 
      CreateCharacter("Aragorn") 
  };                                  

  // Aragorn will be automatically deleted
  // when it goes out of scope
}

Caution with Temporary Access

Be careful when using get() with functions that might store the pointer for later use:

#include <memory>
#include <string>
#include <vector>

class Character {
public:
  std::string Name;
};

std::vector<Character*> CharacterRegistry;

void RegisterCharacter() {
  auto Boromir{std::make_unique<Character>("Boromir")};
  CharacterRegistry.push_back(Boromir.get());
}

int main() {
  RegisterCharacter();

  // Dangerous! CharacterRegistry now has
  // a dangling pointer
}

In this case, CharacterRegistry will have a dangling pointer once Boromir goes out of scope and is deleted.

Remember, when using unique_ptr with C-style APIs, you're responsible for ensuring that ownership semantics are respected. Always be clear about who owns the pointer and who is responsible for deleting it.

Answers to questions are automatically generated and may not have been reviewed.

3D art showing a progammer setting up a development environment
Part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access

This course includes:

  • 59 Lessons
  • Over 200 Quiz Questions
  • 95% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved