如何使用智能指针围绕 C 'objects' 实现包装器?
How to implement a wrapper around C 'objects' using smart pointers?
我正在使用一个 C 库,它使用来自 C++ 的原始指针。因此,我正在研究将所有指向 C 对象的指针包装在 C++ classes 中并将它们变成智能指针。我建立了一个工作示例:
#include <iostream>
using namespace std;
// the C library is oop: using structs and naming conventions. Like this:
// C library declarations
struct Animal_s {
int age;
};
typedef struct Animal_s Animal;
Animal* make_animal(int age);
void free_animal(Animal* animal);
Animal* do_something_with_animal(Animal* animal);
// C lib implementations
Animal* make_animal(int age ){
auto* animal = (Animal*) malloc(sizeof(Animal));
animal->age = age;
return animal;
}
void free_animal(Animal *animal){
free(animal);
}
Animal* do_something_with_animal(Animal* animal){
//...
return animal;
}
// C++ wrapper
class AnimalWrapper{
Animal* animal_; // how to use smart pointers?
public:
explicit AnimalWrapper(int age){
animal_ = make_animal(age);
};
~AnimalWrapper(){
free_animal(animal_);
}
AnimalWrapper(const AnimalWrapper& animalWrapper){
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
}
AnimalWrapper(AnimalWrapper&& animalWrapper) noexcept {
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
}
AnimalWrapper& operator=(const AnimalWrapper& animalWrapper) {
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
return *this;
}
AnimalWrapper& operator=(AnimalWrapper&& animalWrapper) noexcept {
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
return *this;
}
Animal *getAnimal() const {
return animal_;
}
Animal* doSomethingWithAnimal(){
return do_something_with_animal(animal_);
}
};
int main(){
AnimalWrapper animalWrapper(6);
return 0;
};
这个例子有效,并且根据 valgrind,正确地管理了内存。但是,是否可以使用智能指针实现包装器 class ?还是我必须手动管理包装器 classes 中的内存?
您不能在 C 中使用任何 C++ 问题。您正在做的是将 C 代码与 C++ 编译器一起使用,因为 C 不支持类似
的东西
using namespace something;
一般来说,如果您将指针传递给尚未声明的对象 extern "C"
,您将 运行 陷入困境。
您对针对 C++ 使用 C 构造感到非常困惑。如果你声明了一个 struct A
就没有必要 typedef struct A A;
因为这在 C++ 中是隐含的。但这不可能是 C,因为你 use namespace
在你的源代码中....
要在您的代码中使用 C 库,您需要将(仅在 C++ 中)声明为 extern "C"
,否则链接器将很难找到它(由于 C++ 对标识符进行名称处理以支持超载)
我猜不到你能在这种情况下获得完整的编译。
您可以使用 std::unique_ptr
来管理 Animal
个对象的生命周期:
#include <memory>
struct FreeAnimal {
void operator()(Animal* a) const noexcept {
free_animal(a);
}
};
using AnimalPtr = std::unique_ptr<Animal, FreeAnimal>;
int main() {
AnimalPtr party_animal{make_animal(21)};
do_something_with_animal(&*party_animal);
// or
do_something_with_animal(party_animal.get());
}
我正在使用一个 C 库,它使用来自 C++ 的原始指针。因此,我正在研究将所有指向 C 对象的指针包装在 C++ classes 中并将它们变成智能指针。我建立了一个工作示例:
#include <iostream>
using namespace std;
// the C library is oop: using structs and naming conventions. Like this:
// C library declarations
struct Animal_s {
int age;
};
typedef struct Animal_s Animal;
Animal* make_animal(int age);
void free_animal(Animal* animal);
Animal* do_something_with_animal(Animal* animal);
// C lib implementations
Animal* make_animal(int age ){
auto* animal = (Animal*) malloc(sizeof(Animal));
animal->age = age;
return animal;
}
void free_animal(Animal *animal){
free(animal);
}
Animal* do_something_with_animal(Animal* animal){
//...
return animal;
}
// C++ wrapper
class AnimalWrapper{
Animal* animal_; // how to use smart pointers?
public:
explicit AnimalWrapper(int age){
animal_ = make_animal(age);
};
~AnimalWrapper(){
free_animal(animal_);
}
AnimalWrapper(const AnimalWrapper& animalWrapper){
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
}
AnimalWrapper(AnimalWrapper&& animalWrapper) noexcept {
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
}
AnimalWrapper& operator=(const AnimalWrapper& animalWrapper) {
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
return *this;
}
AnimalWrapper& operator=(AnimalWrapper&& animalWrapper) noexcept {
if (this != &animalWrapper){
animal_ = animalWrapper.animal_;
}
return *this;
}
Animal *getAnimal() const {
return animal_;
}
Animal* doSomethingWithAnimal(){
return do_something_with_animal(animal_);
}
};
int main(){
AnimalWrapper animalWrapper(6);
return 0;
};
这个例子有效,并且根据 valgrind,正确地管理了内存。但是,是否可以使用智能指针实现包装器 class ?还是我必须手动管理包装器 classes 中的内存?
您不能在 C 中使用任何 C++ 问题。您正在做的是将 C 代码与 C++ 编译器一起使用,因为 C 不支持类似
的东西using namespace something;
一般来说,如果您将指针传递给尚未声明的对象 extern "C"
,您将 运行 陷入困境。
您对针对 C++ 使用 C 构造感到非常困惑。如果你声明了一个 struct A
就没有必要 typedef struct A A;
因为这在 C++ 中是隐含的。但这不可能是 C,因为你 use namespace
在你的源代码中....
要在您的代码中使用 C 库,您需要将(仅在 C++ 中)声明为 extern "C"
,否则链接器将很难找到它(由于 C++ 对标识符进行名称处理以支持超载)
我猜不到你能在这种情况下获得完整的编译。
您可以使用 std::unique_ptr
来管理 Animal
个对象的生命周期:
#include <memory>
struct FreeAnimal {
void operator()(Animal* a) const noexcept {
free_animal(a);
}
};
using AnimalPtr = std::unique_ptr<Animal, FreeAnimal>;
int main() {
AnimalPtr party_animal{make_animal(21)};
do_something_with_animal(&*party_animal);
// or
do_something_with_animal(party_animal.get());
}