此代码在(*function)()
崩溃。我正在运行Visual Studio 2019并为Windows 10 x86_64编译C ++ 17。我已经在具有GCC(-std = c ++ 17)的Linux上对其进行了测试,并且工作正常。我想知道这是否是Visual Studio的C ++编译器有问题或我没有看到的问题。
#include <vector>
#include <array>
#include <functional>
#include <iostream>
int main() {
const size_t blockSize = sizeof(std::function<void()>);
using block = std::array<char, blockSize>;
std::vector<block> blocks;
auto lambda = [](){
std::cout << "The lambda was successfully called.\n";
};
blocks.emplace_back();
new (&blocks[0]) std::function<void()>(lambda);
blocks.emplace_back();
new (&blocks[1]) std::function<void()>(lambda);
std::function<void()> *function = (std::function<void()> *)blocks[0].data();
(*function)();
return 0;
}
该错误是std :: function内部的读访问冲突。
[将元素附加到std::vector
时,该元素会使向量的大小大于其容量,向量必须分配新的存储并将其所有元素复制/移动到新的空间。在向量中保存的std::function
数组中构造了复杂的char
对象时,向量不知道这一点。构成std::function
对象的基础字节将被复制到向量的新存储中,但是std::function
的复制/移动构造方法将不会被调用。
最佳解决方案是直接使用std::vector<std::function<void()>>
。如果出于某些原因have使用原始存储块向量,那么在开始插入元素之前,您需要预先分配空间。即
int main() {
const size_t blockSize = sizeof(std::function<void()>);
using block = std::array<char, blockSize>;
std::vector<block> blocks;
auto lambda = [](){
std::cout << "The lambda was successfully called.\n";
};
blocks.reserve(2); // pre-allocate space for 2 blocks
blocks.emplace_back();
new (&blocks[0]) std::function<void()>(lambda);
blocks.emplace_back();
new (&blocks[1]) std::function<void()>(lambda);
std::function<void()> *function = (std::function<void()> *)blocks[0].data();
(*function)();
return 0;
}
或者,您可以使用其他数据结构,例如std::list
,该结构在添加或删除元素时保持稳定的地址。