使用带有std :: function的新展示位置无效

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

此代码在(*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内部的读访问冲突。

c++ c++17 visual-studio-2019 std-function placement-new
1个回答
4
投票

[将元素附加到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;
}

Live Demo

或者,您可以使用其他数据结构,例如std::list,该结构在添加或删除元素时保持稳定的地址。

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