为什么我们不能轻易复制std :: function

Xu *_*Pan 12 c++ c++11 std-function

我要问这个的原因是我需要存储std::function在一个向量中,而我们公司内部的向量基本上是在需要更多内存的情况下进行realloc.(基本上memcpy,没有复制/移动操作员参与)

这意味着我们可以放入容器中的所有元素都需要可以轻松复制.

这里有一些代码来演示我有问题的副本:

void* func1Buffer = malloc(sizeof(std::function<void(int)>));
std::function<void(int)>* func1p = new (func1Buffer) std::function<void(int)>();
std::function<void(int)>* func2p = nullptr;
*func1p = [](int) {};
char func2Buffer[sizeof(*func1p)];
memcpy(&func2Buffer, func1p, sizeof(*func1p));
func2p = (std::function<void(int)>*)(func2Buffer);
// func2p is still valid here
(*func2p)(10);
free(func1Buffer);
// func2p is now invalid, even without std::function<void(int)> desctructor get triggered
(*func2p)(10);
Run Code Online (Sandbox Code Playgroud)

我知道我们应该支持元素的复制/移动以便std::function安全存储.但我仍然很好奇std::function上面无效复制的直接原因是什么.

-------------------------------------------------- --UpdateLine ----------------------------------------------- -----

更新了代码示例.

通过调试我们的内部向量,我找到了这种失败的直接原因.

平凡的复制std::function有一些依赖于原始对象的内存,删除原始内存将垃圾严重复制std::function甚至没有原始对象的破坏.

感谢大家对这篇文章的回答.这都是有价值的投入.:)

Bar*_*rry 7

问题是如何std::function实现:它必须管理它所持有的任何对象的生命周期.所以当你写:

{
    std::function<Sig> f = X{};
} 
Run Code Online (Sandbox Code Playgroud)

我们必须Xf超出范围时调用析构函数.此外,std::function[可能]将分配内存来保存,X因此析构函数也f必须[可能]释放该内存.

现在考虑当我们尝试时会发生什么:

char buffer[100000]; // something big
{
    std::function<void()> f = X{};
    memcpy(buffer, &f, sizeof(f));
}
(*reinterpret_cast<std::function<void()>*>(buffer))();
Run Code Online (Sandbox Code Playgroud)

在我们调用函数"存储"的时候buffer,X对象已经被破坏,并且已经[可能]释放了存放它的内存.不管XTriviallyCopyable,我们没有一个X了.我们这位艺术家以前被称为X.

因为它有责任std::function管理自己的对象,所以TriviallyCopyable 即使我们添加了它管理的所有可调用对象的要求也是如此TriviallyCopyable.


要在你的工作中realloc_vector,你需要像function_ref(或std::function<>*)那样的东西(也就是说,一种根本没有任何资源的类型),或者你需要实现自己的版本function(a)将自己的存储保存为成员避免分配内存(b)只能用TriviallyCopyable可调用内容构造,以便它本身变得可以轻易复制.哪种解决方案更好取决于您的程序实际执行的操作.