2024-02-04 混用 C 与 C++ 的 calloc 和 new 导致的问题


点击 快速C语言入门


混用 C 与 C++ 的 calloc 和 new 导致的问题

  • 前言
  • 一、问题代码
  • 二、使用new
  • 总结


前言

要解决问题: 同样的代码, 含有std::string的结构, 在gcc环境通过calloc可以赋值, 但是在VS下不行

想到的思路: std::string不是平凡类, 按道理不能通过calloc初始化, 会产生问题, 但神奇的gcc却貌似可以正常运行.

其它的补充: 混用CC++真的不是一个好的习惯, 尤其涉及内存分配问题.


一、问题代码

#include 
#include 
#include 

#define MAX_PERSON_COUNT 3

struct Person
{
    std::string m_name;
    int age;
};

int main()
{
    std::string name;
    std::cin >> name;

    Person *test =
        static_cast<Person *>(calloc(MAX_PERSON_COUNT, sizeof(Person)));

    test->m_name = name;

    std::cout << test->m_name;

    return 0;
}

struct Person中有一个std::string, 在C++中, 这是一个需要初始化的元素, 但是calloc不能调用构造函数, 只会分配一块内存, 且内存中的数据都是0.

然而神奇的是, 在gcc环境下, 可以给没有初始化的string赋值,

我们简单分析一下, 如果string的构造是一个指向字符串的指针, 以及一个代表字符长度的整型值,

那么在进行赋值的时候, 会重新开辟一块内存, 并将其地址传递给string内部的指针, 并将字符串拷贝过去

同时, 记录长度的值也传递给字符串的记录长度值的成员变量.

但为了保证性能, 可能string在初始化时默认分配一个足够大的空间, 处理小字符串,

如果在赋值时, 长度未超过这个范围, 直接拷贝字符串到内存中,

那此时calloc不能初始化的string在赋值时, 就有了隐患.

而我们不能保证string的具体实现, 所以, 用calloc分配带有非平凡类的string也就不能保证是否可用.

二、使用new

#include 
#include 
#include 

#define MAX_PERSON_COUNT 3

struct Person
{
    std::string m_name;
    int age;
};

int main()
{
    std::string name;
    std::cin >> name;

    Person *test = new Person[MAX_PERSON_COUNT];
    //       static_cast(calloc(MAX_PERSON_COUNT, sizeof(Person)));

    test->m_name = name;

    std::cout << test->m_name;

    return 0;
}

new就意味着, 在C++中, 编译器会将结构当作类来处理, 使用默认构造函数, 那么string会被正确初始化, 无论它是如何实现的, 在任何编译器将可正确运行.


总结

混用CC++并不是一个好的习惯, 同时, 这是两种语言, 虽然绝大部分是兼容的, 但我相信, 绝大部分人无法区分, 在任意编译器下, 它们的区分究竟是什么, 这里坑恐怕不少, 如果你有试错的本钱, 可随意, 但如果没有, 还是让上帝的归上帝, 凯撒的归凯撒吧.


点击 快速C语言入门


你可能感兴趣的:(笔记,c++,c语言)