struct 在c中是结构体体,在c++ 中升级为class 了,他拥有类的全部特征。

不过和class 还是有区别的,struct成员包含的函数、变量默认都有public的访问权限。

#include <iostream>

struct ConfigModel {
    std::string model_path;
    bool is_rgb;
    int input_w;
    int input_h;
};

int main()
{
    //声明一个结构体,对结构体中的每个元素赋值
    ConfigModel config;
    config.model_path = "yolov5.onnx";
    config.is_rgb = false;
    config.input_w = 640;
    config.input_h = 640;

    //初始化,直接赋值
    ConfigModel config1 = { "yolov5.onnx" ,false,640,640 };

    //定义结构体数组
    ConfigModel configs[4] = {
        {"yolov5a.onnx" ,false,640,640},
        {"yolov5b.onnx" ,false,640,640},
        {"yolov5c.onnx" ,false,640,640},
        {"yolov5d.onnx" ,false,640,640}
    };


    //结构体整体赋值
    ConfigModel config2 = config1;
    std::cout << config2.model_path << std::endl;

    //结构体指针,用->来访问成员变量
    ConfigModel* cf = &config1;
    std::cout << cf->is_rgb << std::endl;
    //结构体数组的成员变量访问
    std::cout << configs[2].model_path << std::endl;

    //打印出结构体元素的地址
    printf("%p\n", &(configs[0].model_path));
    printf("%p\n", &(configs[0].is_rgb));
    std::cout << &(configs[0].input_w) << std::endl;
    std::cout << &(configs[0].input_h) << std::endl;

    system("pause");
    return 0;
}

C语言中结构体使用:struct ConfigModel config = {...}; 关键字struct不能漏,但在c++中,可以直接使用ConfigModel config来定义结构体变量。

typedef的用法

struct ConfigModel {
    std::string model_path;
    bool is_rgb;
    int input_w;
    int input_h;
}config;

typedef struct ConfigModel2 {
    std::string model_path;
    bool is_rgb;
    int input_w;
    int input_h;
}CONFIG;

int main()
{
    config = { "yolov5a.onnx" ,false,640,640 };
    std::cout << config.model_path << std::endl;
    CONFIG config1 = { "yolov5b.onnx" ,false,640,640 };
    std::cout << config1.model_path << std::endl;

    system("pause");
    return 0;
}

在该例子中,config是struct ConfigModel声明的一个结构体变量,CONFIG是struct ConfigModel2的同义字,可以使用CONFIG来定义变量。

对于typedef struct ConfigModel{...}CONFIG,结构体类型名就相当于"struct 结构体名",在该例子中,CONFIG相当于struct ConfigModel的别名。

在C语言编程中是不允许在定义结构体变量时省略struct关键字,当然C++中用不用的结果都是一样的,所以有时候为了平台的兼容性以及代码更好的可读性,使用typedef关键字。

结构体数值清零

1.手动赋值为0,结构体定义之后,将每个成员都赋值为0。

struct MyStruct {
    int a;
    char b;
    float c;
};
 
struct MyStruct myStruct = { 0 };

2.使用memset函数,将结构体中的所有成员都赋值为0。

struct MyStruct myStruct;
 
memset(&myStruct, 0, sizeof(struct MyStruct));

结构体的浅拷贝和深拷贝 

1.浅拷贝指的是仅拷贝对象的所有成员,而不包括其引用对象,例如指针指向的其他内容。

typedef struct Student
{
    int age;
    char *name;

    Student()
    {
        age = 10;
        name = new char[100];
        strcpy(name, "JackMa");
    }
} STUDENT;

// 浅拷贝
int main()
{
    STUDENT stu1;
    std::cout << stu1.age << " " << stu1.name << std::endl;

    std::cout << "-------------------qian_copy---------------" << std::endl;
    STUDENT stu2 = stu1;
    strcpy(stu1.name, "PeterLi");
    std::cout << stu2.age << " " << stu2.name << std::endl;

    free(stu1.name);
    // free(stu2.name);

    return 0;
}

运行结果: 

 

 在改变了stu1的指针对象的内容之后,stu2的指针对象的内容也变化了;先将stu1.name的内存释放之后,在free(stu2.name)的时候会报错,说明使用=进行的拷贝是浅拷贝,两者指针指向的同一片内存区域。

2.深拷贝除了拷贝其成员本身的值之外,还拷贝的成员指向的动态内存区域等类似的内容。

// 深拷贝
int main()
{
    STUDENT stu1;
    std::cout << stu1.age << " " << stu1.name << std::endl;

    std::cout << "-------------------shen_copy---------------" << std::endl;
    STUDENT stu2;
    stu2.age = stu1.age;
    std::memcpy(stu2.name, stu1.name, 100 * sizeof(char));
    std::cout << stu2.age << " " << stu2.name << std::endl;
    strcpy(stu1.name, "PeterLi");
    std::cout << stu2.age << " " << stu2.name << std::endl;

    free(stu1.name);
    free(stu2.name);

    return 0;
}

运行结果:

 

 在改变了stu1.name的内容之后,stu2.name的内容维持不变,说明两者互不影响,是独立的内存空间。进行深拷贝需要重新申请指针的内存空间,使用memcpy进行字节的拷贝。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐