将 placement new 与 std::function 一起使用不起作用
Using placement new with an std::function doesn't work
此代码在 (*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
并且该元素会使向量的大小大于其容量时,向量必须分配新的存储空间并且 copy/move 它的所有元素都分配给新的 space。虽然您在向量中保存的 char
数组中构造了复杂的 std::function
对象,但向量并不知道这些。构成 std::function
对象的底层字节将被复制到向量的新存储中,但不会调用 std::function
的 copy/move 构造函数。
最好的解决方案是直接使用 std::vector<std::function<void()>>
。如果您出于某种原因必须 使用原始存储块向量,那么您需要在开始插入元素之前预先分配space。即
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
,它在添加或删除元素时保持稳定的地址。
此代码在 (*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
并且该元素会使向量的大小大于其容量时,向量必须分配新的存储空间并且 copy/move 它的所有元素都分配给新的 space。虽然您在向量中保存的 char
数组中构造了复杂的 std::function
对象,但向量并不知道这些。构成 std::function
对象的底层字节将被复制到向量的新存储中,但不会调用 std::function
的 copy/move 构造函数。
最好的解决方案是直接使用 std::vector<std::function<void()>>
。如果您出于某种原因必须 使用原始存储块向量,那么您需要在开始插入元素之前预先分配space。即
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
,它在添加或删除元素时保持稳定的地址。