是否可以将一个已经初始化的变量变成一个void*?

问题描述 投票:0回答:1

这是一个关于语言局限性的问题,请不要回答 "你不应该这样做",这与你是否是 与否,重要的是你是否 可以.

假设我们想写一个子程序来获得任何对象的所有权,我们可以这样写,例如。

void function(void* object)
{
   // store the pointer somewhere
}

auto ptr = new MyObject(params);
function(ptr);

上面的程序是可行的,但是强迫用户用下面的函数初始化他想存储的对象 new 操作符。我想知道你是否可以 "窃取 "对象的内容,即使它是正常初始化的。

我想知道你是否可以做这样的事情。

template <typename T>
void function(T& object)
{
   void* ptr = malloc(sizeof(T));
   *ptr = std::move(object); // Or somehting like this
   // store ptr somewhere
}

MyObject object(params);
function(object);
// object variable is now invalid
c++ pointers memory void-pointers
1个回答
1
投票

你当然可以从一个不是动态分配的东西,你可以移动到一个不是动态分配的东西,你可以移动到一个 动态分配。

但这只有在 "移动 "对你的类型有意义和价值时才有用。否则你就只能复制数据了。

请记住,"移动 "并不是真正意义上的转移或改变对象。std::move 实际上并不移动对象,也就是转移或改变它们的寿命;它只是让编译器选择构造函数和赋值操作符重载 执行一些间接状态的廉价转移,以避免深度复制的成本。


1
投票

假设我们想写一个子程序,获取any对象的所有权。

单纯用void指针肯定是不行的,因为所有权意味着要负责删除动态对象,不可能通过void指针来删除一个对象。

可以通过使用deleter函数对象来实现。没有必要为此写一个封装类,因为标准库已经为你覆盖了1.

我想知道你是否可以做一些类似的事情。

void* ptr = malloc(sizeof(T));
*ptr = std::move(object);

不完全是这样, 因为你不能通过指针间接到void, 而且, 你一开始并没有在那里创建一个对象, 所以没有什么可分配的.

从l值引用参数中移动也是一个坏主意。

你似乎想做的是创建一个动态对象,它是参数对象的副本(通过移动)。下面是一个如何做到这一点的例子。

template <typename T>
void function(T&& object)
{
    auto ptr = std::make_unique<T>(std::move(object));

你可以像这样得到一个指向void的指针。

void* void_ptr = ptr.get();

1 为了类型擦除任何类型的对象(就像用void指针可以实现的那样),同时也能拥有这个对象(与void指针不同),在标准库中有一个类型。std::any.

© www.soinside.com 2019 - 2024. All rights reserved.