我有一个可以包含指向某些数据及其数据类型的指针的类。 因此,每时每刻我都可以使用强制类型正确的数据来处理这些数据。
以下是int和float的示例:
enum MyType {
NO_TYPE,
INT,
FLO
};
class MyClass {
public:
MyType type;
void* data;
MyClass(int i)
:
type(MyType::INT)
{
data = (void*) new int(i);
}
MyClass(float i)
:
type(MyType::FLO)
{
std::cout << "Constructor\n";
data = (void*) new float(i);
}
MyClass()
:
type(MyType::NO_TYPE)
{
std::cout << "Constructor (default)\n";
data = nullptr;
}
void Copy(const MyClass &from)
{
this->type = from.type;
if (this->type == MyType::INT)
this->data = (void*) new int (*((int*)from.data));
if (this->type == MyType::FLO)
this->data = (void*) new float (*((float*)from.data));
}
MyClass(MyClass &from) {
std::cout << "Copy constructor\n";
Copy((const MyClass&)from);
}
MyClass(const MyClass &from) {
std::cout << "Copy constructor\n";
Copy(from);
}
~MyClass() {
std::cout << "Destructor for type " << this->type << "\n";
if (this->type == MyType::INT)
delete (int*)this->data;
if (this->type == MyType::FLO)
delete (float*)this->data;
this->data = nullptr;
}
};
我想用shared_ptr
重写它。但是我的主要问题是data
是void*
。有一些技巧可以帮助我吗?
更新:
编写此类的主要目的是将一些不同的数据存储在一个队列中
像queue<MyClass>
答案 0 :(得分:4)
我无法说出使用shared_ptr<void>
的价值,但是它可以用作指针的通用容器。
这些有效:
int i = 42;
std::shared_ptr<void> spVoid = std::make_shared<int>(i);
float f = 3.14f;
std::shared_ptr<void> spVoid = std::make_shared<float>(f);
当最后一个引用消失时,将调用原始实例化项目的正确析构函数。通过类实例亲自查看。
struct Foo
{
Foo()
{
std::cout << "Foo constructor" << std::endl;
}
~Foo()
{
std::cout << "Foo destructor" << std::endl;
}
};
int main()
{
std::shared_ptr<void> spVoid = std::make_shared<Foo>();
return 0;
}
关于向上传播shared_ptr的唯一警告是关于跨越DLL边界。如果在DLL或共享库单元之间传递了shared_ptr实例,则原始类型(和正确的析构函数)可能会丢失。
答案 1 :(得分:0)
有太多未知数无法单方面回答。
std::variant
unsigned char*
答案 2 :(得分:0)
有一些技巧可以帮助我吗?
您当然可以做到。这是您班级的更新版本,其中包含一些测试代码。
#include <iostream>
#include <memory>
enum MyType {
NO_TYPE,
INT,
FLO
};
class MyClass {
public:
MyType type;
std::shared_ptr<void> data;
static void int_deleter(int* ptr)
{
std::cout << "Deleting an int*\n";
delete ptr;
}
static void float_deleter(float* ptr)
{
std::cout << "Deleting a float*\n";
delete ptr;
}
MyClass(int i) : type(MyType::INT), data(new int(i), int_deleter)
{
std::cout << "Constructor with int\n";
}
MyClass(float i) : type(MyType::FLO), data(new float(i), float_deleter)
{
std::cout << "Constructor with float\n";
}
MyClass() : type(MyType::NO_TYPE)
{
std::cout << "Constructor (default)\n";
}
// Can be a private member function.
static std::shared_ptr<void> make_data(const MyClass &from)
{
switch ( from.type )
{
case MyType::INT:
return std::shared_ptr<void>(new int (*((int*)from.data.get())), int_deleter);
case MyType::FLO:
return std::shared_ptr<void>(new float (*((float*)from.data.get())), float_deleter);
default:
return {};
}
return {};
}
MyClass(MyClass &from) : type(from.type), data(make_data(from))
{
std::cout << "Copy constructor\n";
}
MyClass(const MyClass &from) : type(from.type), data(make_data(from))
{
std::cout << "Copy constructor\n";
}
~MyClass()
{
std::cout << "Destructor for type " << this->type << "\n";
}
};
void test_int()
{
MyClass c1(10);
MyClass c2(c1);
}
void test_float()
{
MyClass c1(10.2f);
MyClass c2(c1);
}
int main()
{
test_int();
test_float();
}
输出:
Constructor with int
Copy constructor
Destructor for type 1
Deleting an int*
Destructor for type 1
Deleting an int*
Constructor with float
Copy constructor
Destructor for type 2
Deleting a float*
Destructor for type 2
Deleting a float*
答案 3 :(得分:0)
您可以提供Deleter :(默认情况下是正确的,因此可以使用std::make_shared
)。
class MyClass {
public:
MyType type = MyType::NO_TYPE;
std::shared_ptr<void> data;
MyClass() = default;
MyClass(int i) { set(i); }
MyClass(float f) { set(f); }
void Copy(const MyClass &from)
{
switch (from.type) {
case MyType::INT: set(*((int*)from.data.get());
case MyType::FLO: set(*((float*)from.data.get());
case MyType::NO_TYPE: set();
}
}
MyClass(const MyClass &from) {
std::cout << "Copy constructor\n";
Copy(from);
}
void set()
{
type = MyType::NO_TYPE;
data = nullptr;
}
void set(int i)
{
type = MyType::INT;
data = std::make_shared<int>(i);
}
void set(float f)
{
type = MyType::FLO;
data = std::make_shared<float>(f);
}
~MyClass() = default;
};