使用std::vector创建vk::raii::ImageView触发默认构造函数删除错误
问题:Vulkan RAII创建ImageView向量时编译报错
我尝试通过以下函数将std::vector<VkImage>映射为std::vector<vk::raii::ImageView>,实现参考了官方示例,但编译时出错,提示vk::raii::ImageView的默认构造函数已被删除。确认错误由这段代码导致,想知道这是vulkan_raii.hpp的问题,还是应该改用非RAII版本创建ImageView?
代码实现
std::vector<vk::raii::ImageView> Render::createImageViews( std::vector<VkImage>& images, vk::raii::Device& device ) { std::vector<vk::raii::ImageView> views(images.size()); vk::ImageViewCreateInfo createInfo( {}, {}, vk::ImageViewType::e2D, vk::Format::eB8G8R8A8Srgb, {}, { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } ); for (size_t i = 0; i < images.size(); i++) { createInfo.image = images[i]; views[i] = std::move( vk::raii::ImageView(device, createInfo) ); } return views; }
编译错误信息
make RUN=1 mkdir -p build/debug/obj g++ -c -std=c++17 -Wall -pedantic -g -D ENABLE_VK_VALIDATION_LAYERS -D ENABLE_DEBUG_LOG -D VULKAN_HPP_NO_SMART_HANDLE -D VULKAN_HPP_NO_SPACESHIP_OPERATOR -D VULKAN_HPP_NO_TO_STRING -D VULKAN_HPP_NO_SETTERS src/render.cpp -o build/debug/obj/render.o In file included from /usr/include/c++/11/optional:44, from src/render.hpp:3, from src/render.cpp:1: /usr/include/c++/11/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_Tp*, _Args&& ...) [with _Tp = vk::raii::ImageView; _Args = {}]’: /usr/include/c++/11/bits/stl_uninitialized.h:579:18: required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = vk::raii::ImageView*; _Size = long unsigned int; bool _TrivialValueType = false]’ /usr/include/c++/11/bits/stl_uninitialized.h:640:20: required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = vk::raii::ImageView*; _Size = long unsigned int]’ /usr/include/c++/11/bits/stl_uninitialized.h:704:44: required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = vk::raii::ImageView*; _Size = long unsigned int; _Tp = vk::raii::ImageView]’ /usr/include/c++/11/bits/stl_vector.h:1606:36: required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = vk::raii::ImageView; _Alloc = std::allocator<vk::raii::ImageView>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’ /usr/include/c++/11/bits/stl_vector.h:512:9: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = vk::raii::ImageView; _Alloc = std::allocator<vk::raii::ImageView>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<vk::raii::ImageView>]’ src/render.cpp:121:57: required from here /usr/include/c++/11/bits/stl_construct.h:119:7: error: use of deleted function ‘vk::raii::ImageView::ImageView()’ 119 | ::new(static_cast<void*>(__p)) _Tp(std::forward<_Args>(__args)...); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from src/render.hpp:12, from src/render.cpp:1: /usr/include/vulkan/vulkan_raii.hpp:7501:7: note: declared here 7501 | ImageView() = delete; | ^~~~~~~~~ make: *** [Makefile:44: build/debug/obj/render.o] Error 1
问题原因与解决方法
原因
报错核心是:std::vector<vk::raii::ImageView> views(images.size());这行代码会创建一个包含images.size()个元素的向量,而vector的这种构造方式会尝试默认构造每个元素。但vk::raii::ImageView作为RAII类,其默认构造函数被显式删除(设计上不允许存在无资源的空对象),因此编译失败。
解决方法
完全不需要改用非RAII版本,RAII是Vulkan官方推荐的资源管理方式,能自动释放资源避免泄漏。只需修改vector的初始化和元素添加方式:
优化后的代码
std::vector<vk::raii::ImageView> Render::createImageViews( std::vector<VkImage>& images, vk::raii::Device& device ) { std::vector<vk::raii::ImageView> views; views.reserve(images.size()); // 预分配空间,避免多次扩容 vk::ImageViewCreateInfo createInfo( {}, {}, vk::ImageViewType::e2D, vk::Format::eB8G8R8A8Srgb, {}, { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } ); for (auto& image : images) { createInfo.image = image; views.emplace_back(device, createInfo); // 直接在vector内存中构造对象 } return views; }
关键改动说明
- 初始化空vector,避免触发默认构造
- 用
reserve预分配足够空间,提升性能 - 用
emplace_back直接在vector的内存区域构造vk::raii::ImageView,跳过默认构造步骤
关于官方示例的疑问
官方示例大概率是用了emplace_back或直接在构造vector时填充元素,而非先创建指定大小的vector再赋值,因此不会触发默认构造。
内容的提问来源于stack exchange,提问作者Artsiom Miksiuk
相关产品推荐
相关产品推荐

