memcpy和vector的搭配使用

有时需要把其他类型的数据(torch::Tensor)转成vector。
1.例子

void tensor2Vect(torch::Tensor& box, vector<float>& boxvect)
{
    std::vector<float>boxvect_new(box.numel(),-1);//[1]
    box = box.to(torch::kCPU);//[2]
    std::memcpy(&boxvect_new[0], box.data_ptr(),box.numel()*sizeof(float ));//[3]
    boxvect = boxvect_new;
 }

总结:
(1) 当使用未初始化大小的vector时,使用memcpy时,被拷贝的对象里面存在动态内存。比如:vector对象大小无法确定,memcpy不管这事直接拷贝sizeof大小的内存,导致vector的内存结构破坏,vector析构时就出错了。因此memcpy和vector的搭配使用时,首先一定要给vector初始化大小,如[1]处实例;
(2) 记得把torch::Tensor转成CPU,如[2]处;
(3) memcpy的第一个参数如果是vector,则不能写成memcpy(&vector,应该写 memcpy(&vector[0],因为&vector[0]是取第一个元素的地址,vector不同于数组,不能用名字代替首地址。
(4) tensor---->vector,直接使用for循环push_back比使用std::memcpy耗时:
----pushback time: 0.096139ms, memcpy time:0.013888ms
----pushback time: 0.099949ms, memcpy time:0.014745ms
----pushback time: 0.097549ms, memcpy time:0.014277ms
----pushback time: 0.105581ms, memcpy time:0.013891ms
----pushback time: 0.097005ms, memcpy time:0.014123ms
----pushback time: 0.104942ms, memcpy time:0.014149ms
----pushback time: 0.096715ms, memcpy time:0.014039ms
----pushback time: 0.10761ms, memcpy time:0.013313ms
----pushback time: 0.102769ms, memcpy time:0.015343ms

### 深拷贝与浅拷贝的概念 在讨论如何复制二维 `std::vector` 数组之前,先理解深拷贝浅拷贝的区别非常重要。浅拷贝仅创建新对象并将原始对象的数据成员逐字节复制到新对象中;而深拷贝不仅会分配新的内存空间给目标对象,还会将源对象的内容真正地复制过去。 对于包含指针或其他间接访问资源的对象来说,如果只做浅拷贝,则两个对象将会共享同一份实际数据,这可能导致未定义行为或者难以调试的问题[^1]。 ### 浅拷贝示例 当处理简单的内置类型时,可以直接通过赋值操作符来完成浅拷贝: ```cpp // 创建一个二维整数向量并初始化 std::vector<std::vector<int>> original = {{1, 2}, {3, 4}}; // 使用默认的赋值运算符执行浅拷贝 std::vector<std::vector<int>> shallow_copy = original; ``` 上述代码片段展示了最基础的方式来进行浅拷贝。由于这里涉及的是基本类型的容器,因此这种方式可以正常工作而不引发任何问题。 ### 深拷贝方法一:使用标准库算法 为了确保完全独立于原版的数据副本,在某些情况下可能需要更复杂的逻辑来实现真正的深拷贝。一种常见做法是借助 `<algorithm>` 头文件里的 `std::copy()` 函数配合迭代器一起使用: ```cpp #include <iostream> #include <vector> #include <algorithm> int main(){ std::vector<std::vector<int>> src{{1, 2},{3, 4}}; // 定义一个新的二维向量用于存储深层复制的结果 std::vector<std::vector<int>> dest; // 调整目的向量大小以匹配源向量 dest.resize(src.size()); // 对每一行应用 std::copy 进行元素级别的复制 for(size_t i=0;i<src.size();++i){ dest[i].resize(src[i].size()); std::copy(src[i].begin(),src[i].end(),dest[i].begin()); } return 0; } ``` 这段程序首先调整了目的地向量的尺寸使其能够容纳来自源头的所有子向量,接着遍历每一个内部的一维向量,并调用了 `std::copy()` 来填充对应的条目[^2]。 ### 深拷贝方法二:利用范围for循环 另一种更加直观且易于维护的方式来达到相同效果就是采用基于范围的for语句: ```cpp #include <iostream> #include <vector> int main(){ std::vector<std::vector<int>> source={{1, 2},{3, 4}}; std::vector<std::vector<int>> destination; // 预留足够的容量避免频繁重新分配内存 destination.reserve(source.size()); // 构建 deep copy 的版本 for(const auto& inner_vec : source){ destination.emplace_back(inner_vec); } return 0; } ``` 这种方法同样实现了完整的深拷贝过程,而且其可读性简洁度更高一些。它通过预先保留适当的空间以及直接插入每个内部向量的新实例完成了整个任务。 ### 关于memcpy的风险提示 需要注意的是,像 `memcpy` 或者其他低级内存操作函数并不适用于复杂结构体(比如含有动态分配部分的标准模板库容器),因为它们无法正确处理这些情况下的所有权转移等问题。尝试这样做可能会导致严重的错误,例如悬空指针、双重释放等严重缺陷[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值