C++内存管理之拷贝memcpy、分配malloc 与释放free

1.内存拷贝 memcpy

  • C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。
#声明:
void *memcpy(void *str1, const void *str2, size_t n)

#**********************
str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。
n -- 要被复制的字节数。
- 该函数返回一个指向目标存储区 str1 的指针。
  • memcpy源码如下:
void *memcpy(void *dst, const void *src, size_t size)
{
    char *psrc;
    char *pdst;

    if (NULL == dst || NULL == src)
    {
        return NULL;
    }

    if ((src < dst) && (char *)src + size > (char *)dst) // 出现地址重叠的情况,自后向前拷贝
    {
        psrc = (char *)src + size - 1;
        pdst = (char *)dst + size - 1;
        while (size--)
        {
            *pdst-- = *psrc--;
        }
    }
    else
    {
        psrc = (char *)src;
        pdst = (char *)dst;
        while (size--)
        {
            *pdst++ = *psrc++;
        }
    }

    return dst;
}

1.1 拷贝字符数据

// 将字符串复制到数组 dest 中
#include <stdio.h>
#include <string.h>
 
int main ()
{
   const char src[50] = "http://www.runoob.com";
   char dest[50];
 
   memcpy(dest, src, strlen(src)+1);
   printf("dest = %s\n", dest);
   
   return(0);
}

#******************
output:
dest = http://www.runoob.com
  • 将 s 中第 11 个字符开始的 6个连续字符复制到 d 中:
#include <stdio.h>
#include<string.h>
 
int main()
 
{
  char *s="http://www.runoob.com";
  char d[20];
  memcpy(d, s+11, 6);// 从第 11 个字符(r)开始复制,连续复制 6 个字符(runoob)
  // 或者 memcpy(d, s+11*sizeof(char), 6*sizeof(char));
  d[6]='\0';
  printf("%s", d);
  return 0;
}

#********************
output:
runoob

1.2 拷贝图像数据

  • C++_缓存相机图像数据到内存
#相机原始输出的图像数据是Byer格式,可以塞进内存中的图像数组

unsigned char* imgData[150] ;//创建图像数据数组
 
//初始化时申请缓存150张图像的内存空间
for (int i = 0; i < 150; i++)
{
	imgData[i] = new unsigned char[1280 * 1024];
}
 
//采集到图像后将图像数据拷贝到数组中,pBuffer为相机图像帧数据的内存地址
memcpy(imgData[Pic_num], pBuffer, 1280 * 1024);
 
//完成操作后释放申请的内存空间
for (int i = 0; i < 150; i++)
{
	delete[] imgData[i];
}
  • 如果有1000张100*100的灰度图像,进行数据拷贝:
//*****************将若干份图像数据拷贝到指定目标中************************************
// 申请需要开辟的目标缓冲区的大小
const int ImageSize = 100 * 100;
const int ImageNums = 1000;
 
char* pData = new char[ImageNums * ImageSize ];  // 1000张100*100的灰度图像
int index = 0;
for(int i = 0; i < ImageNums ; i++)
{
    // 假设图像的数据从文件中读取
    CString strImagePath;
    strImagePath.Format("imageData%d",i);
    Mat src = imread(strImagePath,0);  // 灰度图像加载 大小为100*100
    // 将图像数据拷贝到指定的缓冲区中
    memcpy(pData + index,src.data,ImageSize);
    index += ImageSize;
}
 
//*********************将指定目标中的数据读取出来,拆分为一张张图像*****************
// 上述将1000张图像存入指定的缓存中,那么我们如何将图像取出来呢
index = 0;
for(int i = 0; i < ImageNums ; i++)
{
    Mat dst(100,100,CV_8UC1); // 创建图像
    memcpy(dst.data,pData + index,ImageSize);
    index += ImageSize;
 
    // 已经将图像数据拷贝到指定图像中了
    // 接下来对图像做相关的处理
}
 
// 释放指针
delete[] pData;
pData = NULL;
  • opencv中Mat.data 拷贝:
memcpy(dst.data, src.data, src.step * src.rows);
//or
memcpy(mask_.data, img.data,img.rows * img.cols * img.channels());
  • char数据转float:
    传递参数的时候将float类型的指针转换为char类型的指针,但是一个float占四个字节,而一个char占一个字节,所以问题就处在char data这里,data[0]占一个字节,data[1]占一个字节,而传过来的是两个float,即八个字节,但是我们只使用了八个字节的前两位,即data[0],data[1]。
#include <iostream>
using namespace std;
float calc(char *data)
{
    //目标数据为float型指针,内存为2*4 = 8 个字节
	float fdata[2];
	//将拷贝内存大小设为目标数据内存大小
	memcpy((char*)fdata,data,sizeof(float)*2);
	return fdata[0] * fdata[1];
}
 
int main()
{
	float data[2] = {1,2};
	float ret = calc((char*)data);
	cout << ret << endl;
}
double* featureData=new double[nSamples * nFeatures];
//featureData赋值代码省略
Mat trainFeature(nSamples, nFeatures, CV_64FC1, Scalar(0));
memcpy(trainFeature.data, featureData, (size_t)nSamples * nFeatures * sizeof(double));
  • 拷贝数据的效率举例
    在这里插入图片描述

在这里插入图片描述

2.内存分配 malloc

  • C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。
//声明:
//size -- 内存块的大小,以字节为单位。
//返回值:该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。
void *malloc(size_t size)
  • 使用
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main()
{
   char *str;
 
   /* 最初的内存分配 */
   str = (char *) malloc(15);
   strcpy(str, "runoob");
   printf("String = %s,  Address = %u\n", str, str);
 
   /* 重新分配内存 */
   str = (char *) realloc(str, 25);
   strcat(str, ".com");
   printf("String = %s,  Address = %u\n", str, str);
 
   free(str);
 
   return(0);
}

output:

String = runoob,  Address = 3662685808
String = runoob.com,  Address = 3662685808

3.内存释放 free

  • C 库函数 void free(void *ptr) 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。
//ptr -- 指针指向一个要释放内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果传递的参数是一个空指针,则不会执行任何动作。
//返回值该函数不返回任何值。
void free(void *ptr)
  • 实例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char *str;
 
   /* 最初的内存分配 */
   str = (char *) malloc(15);
   strcpy(str, "runoob");
   printf("String = %s,  Address = %p\n", str, str);
 
   /* 重新分配内存 */
   str = (char *) realloc(str, 25);
   strcat(str, ".com");
   printf("String = %s,  Address = %p\n", str, str);
 
   /* 释放已分配的内存 */
   free(str);
 
   return(0);
}

output:

String = runoob,  Address = 0x7fe4e4c02b10
String = runoob.com,  Address = 0x7fe4e4c02b10

参考:

1.C++如何拷贝多份相同大小的数据以及拷出多份相同大小的数据(memcpy的用法)
2.使用memcpy函数的耗时测试(拷贝不同大小数据量耗时不同)

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
拷贝结构体指针,你可以通过以下步骤来完成: 1. 首先,创建一个新的结构体对象,该对象将用于存储拷贝的数据。 2. 使用适当的内存分配函数(如`malloc`)为新结构体对象分配内存空间。 3. 使用`memcpy`函数将原始结构体指针指向的数据拷贝到新的结构体指针指向的内存空间中。 下面是一个示例代码片段,演示了如何拷贝结构体指针: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int id; char name[20]; } Student; void copyStructPointer(Student* src, Student** dest) { // 为目标指针分配内存空间 *dest = (Student*)malloc(sizeof(Student)); // 拷贝数据 memcpy(*dest, src, sizeof(Student)); } int main() { Student* original = (Student*)malloc(sizeof(Student)); original->id = 1; strcpy(original->name, "John"); Student* copied; copyStructPointer(original, &copied); printf("Original: id = %d, name = %s\n", original->id, original->name); printf("Copied: id = %d, name = %s\n", copied->id, copied->name); free(original); free(copied); return 0; } ``` 在上述示例中,我们定义了一个`Student`结构体,并在`main`函数中创建了一个原始的结构体指针`original`。然后,我们调用`copyStructPointer`函数来拷贝`original`指向的数据,并将拷贝结果存储在`copied`指针中。最后,我们打印出原始和拷贝的结构体的数据,并释放内存空间。 注意,拷贝结构体指针实际上是拷贝指针所指向的数据,而不是重新创建一个指向相同数据的新指针。因此,在使用拷贝后的结构体指针时要小心,确保拷贝指针仍然指向有效的内存空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明月醉窗台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值