T含const成员时如何在std::vector<T>之间执行std::copy操作?
问题解答
问题1:保留foo类const修饰符的解决方案
编译错误的核心原因是std::copy会对已存在的元素执行拷贝赋值操作,而包含const非静态成员的类会被隐式删除拷贝赋值运算符,你提前调用tree.resize(N)先构造了默认foo对象,后续赋值操作天然不合法。
你可以完全保留所有const修饰符,只需要修改全局vector的写入逻辑:放弃提前构造+赋值的方案,改为在目标内存位置原地重建对象,绕开赋值操作即可,const成员仅会在构造阶段初始化,完全符合语法规则。
问题2:移动语义的适用性与优化方案
移动语义完全适用于该场景,和vector要求的连续内存特性没有冲突:
- 连续内存仅约束vector存储的对象本身的地址连续,移动构造是在目标连续地址上构造新对象、转移源对象的堆资源所有权,不会破坏内存连续性
- 包含const成员的类虽然没有移动赋值运算符,但可以正常生成隐式移动构造函数,刚好匹配原地重建对象的逻辑
- 使用移动构造可以避免非平凡类型的深拷贝开销,性能远高于拷贝构造
可运行的修改后代码示例
#include<iostream> #include <vector> const int N = 10; class foo { public: foo(int i) : heavy(i), ptr(nullptr) { } foo() : heavy(0), ptr(nullptr) { } const int heavy; foo * const ptr; }; int main() { std::vector<foo> tree; tree.resize(N); #pragma omp parallel for // 可直接加openMP并行指令,各线程写入偏移无冲突 for (int i = 0; i < N; i += 2) { std::vector<foo> vec_private; vec_private.emplace_back(i); vec_private.emplace_back(i+1); for(int j=0;j<2;j++){ // 先析构原有默认构造的对象 tree[i+j].~foo(); // 原地移动构造新对象,不触发赋值操作,完全兼容const成员 new (&tree[i+j]) foo(std::move(vec_private[j])); // 若需要用拷贝构造,替换为:new (&tree[i+j]) foo(vec_private[j]); } } for (auto& x : tree) std::cout << x.heavy << '\n'; return 0; }
内容的提问来源于stack exchange,提问作者Maverick
相关产品推荐
相关产品推荐

