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.
get()
for Read-Only AccessWhen 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
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
}
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
}
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.
Learn how to manage dynamic memory using unique pointers and the concept of memory ownership