QVector.resize()触发error2280:引用已删除函数问题排查
先给你拆解两个问题的根源,再给出对应的解决方案:
一、QVector触发error 2280的原因与解决
你遇到的error 2280: attempting to reference a deleted function,核心原因是std::unique_ptr是独占所有权的智能指针,它的拷贝构造函数被显式删除了,而Qt 5.6.2版本的QVector在执行resize或者内存扩容时,对移动语义的支持不够完善——当它需要重新分配内存、转移元素时,会尝试调用元素的拷贝构造函数,而不是移动构造函数,这就直接触发了unique_ptr的拷贝禁用限制。
修复方案:避免触发拷贝操作,用移动/emplace方式构建容器
不要直接对空的QVector下标访问并resize,而是先通过emplace_back直接在容器内构造行,或者用std::move转移已构造好的行,这样全程不会触发拷贝:
#include <voxel.h> int main(int argc, char *argv[]) { QVector<QVector<std::unique_ptr<Voxel>>> cVoxel; const int rows = 80, cols = 80; // 预分配空间,减少后续扩容的开销 cVoxel.reserve(rows); for (int i = 0; i < rows; ++i) { // 直接在cVoxel里构造一个空的行vector auto& currentRow = cVoxel.emplace_back(); currentRow.resize(cols); // 此时resize的是空vector,元素是默认构造的空unique_ptr,可安全移动 for (int j = 0; j < cols; ++j) { currentRow[j].reset(new Voxel); } } }
或者你也可以先构造好每一行,再用std::move把行转移到cVoxel中:
for (int i = 0; i < rows; ++i) { QVector<std::unique_ptr<Voxel>> row; row.resize(cols); for (int j = 0; j < cols; ++j) { row[j].reset(new Voxel); } // 用move转移所有权,不会触发拷贝 cVoxel.push_back(std::move(row)); }
二、std::vector下标越界的原因与解决
你换成std::vector后出现的崩溃,是因为你先执行了cVoxel.resize(0),此时容器是空的,没有任何行元素,循环里直接访问cVoxel[i](i从0到79)自然会触发下标越界。
修复方案:先预分配足够的行数量
只需要把cVoxel.resize(0)改成cVoxel.resize(rows),提前创建好80个空的行vector,之后再对每一行resize即可:
#include <voxel.h> #include <vector> int main(int argc, char *argv[]) { std::vector<std::vector<std::unique_ptr<Voxel>>> cVoxel; const int rows = 80, cols = 80; // 先创建80个空的行vector cVoxel.resize(rows); for (int i = 0; i < rows; ++i) { auto& currentRow = cVoxel[i]; currentRow.resize(cols); for (int j = 0; j < cols; ++j) { currentRow[j].reset(new Voxel); } } }
当然也可以用emplace_back来逐行构造,效果是一样的。
额外小建议:试试Qt的QScopedPointer
既然你在Qt环境下,也可以考虑用Qt官方的独占智能指针QScopedPointer替代std::unique_ptr,它和Qt容器的兼容性在老版本中可能更好,用法和unique_ptr几乎一致:
#include <voxel.h> #include <QScopedPointer> int main(int argc, char *argv[]) { QVector<QVector<QScopedPointer<Voxel>>> cVoxel; const int rows = 80, cols = 80; cVoxel.resize(rows); for (int i = 0; i < rows; ++i) { auto& currentRow = cVoxel[i]; currentRow.resize(cols); for (int j = 0; j < cols; ++j) { currentRow[j].reset(new Voxel); } } }
内容的提问来源于stack exchange,提问作者PhilPhil

