这是一个关于语言局限性的问题,请不要回答 "你不应该这样做",这与你是否是 应 与否,重要的是你是否 可以.
假设我们想写一个子程序来获得任何对象的所有权,我们可以这样写,例如。
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
你当然可以从一个不是动态分配的东西,你可以移动到一个不是动态分配的东西,你可以移动到一个 是 动态分配。
但这只有在 "移动 "对你的类型有意义和价值时才有用。否则你就只能复制数据了。
请记住,"移动 "并不是真正意义上的转移或改变对象。std::move
实际上并不移动对象,也就是转移或改变它们的寿命;它只是让编译器选择构造函数和赋值操作符重载 可 执行一些间接状态的廉价转移,以避免深度复制的成本。
假设我们想写一个子程序,获取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
.