在struct C ++

时间:2015-04-22 09:22:37

标签: c++ string struct

我正在创建名为struct的{​​{1}}。为了存储名称,仅在student中声明char指针而不是具有预定义大小的struct数组是否有任何问题?然后我可以将字符串文字分配给主代码中的char指针。

char

6 个答案:

答案 0 :(得分:7)

不要使用它们,请使用std::string。我(和许多其他人)保证与char*char[]相比:

  1. 它将更容易使用和
  2. 它不太容易出错。

答案 1 :(得分:5)

差异与静态和动态内存分配之间的差异相同。对于前者(静态),您必须指定足以存储名称的大小,而后者则必须注意在不需要时删除它。

尽管使用std::string已经好了。

答案 2 :(得分:3)

TL; DR - 使用std::string,正如我们在c++中所说的那样。

编辑:之前,根据C标记(目前已移除)

根据您的要求,分配字符串文字需要一个指针,无论如何都不能用数组做。

如果您使用该指针存储字符串文字的基地址,那就没问题。否则,你需要

  • 在使用该指针之前分配内存
  • 完成后,
  • 释放内存。

#)编译时分配数组的基地址无法更改,因此assignment将无效。

答案 3 :(得分:3)

除非有充分的理由不这样做,否则我建议您使用方便的字符串类,例如 std::string ,而不是原始的char*指针。

使用std::string会大大简化您的代码,例如结构将自动复制,字符串将自动释放等。

您无法使用std::string的原因是因为您正在设计界面边界,例如Win32 API主要是基于C接口的(实现可以是C ++),所以你不能在边界使用C ++,而必须使用纯C. 但如果情况并非如此,请帮自己一个忙,并使用std::string

另请注意,如果您必须使用原始char*指针,则需要澄清几个设计问题,例如:

  1. 这是拥有指针,还是观察指针?

  2. 如果它是一个拥有指针,它以什么方式分配,以及它以什么方式发布? (例如malloc() / free()new[] / delete[],其他分配器,如COM CoTaskMemAlloc()SysAllocString()等。

  3. 如果它是一个观察指针,你必须确保观察到的字符串的生命周期超过了观察指针的生命周期,以避免悬挂引用。

  4. 如果您使用方便的字符串类(例如std::string),则所有这些问题都不存在。

    另请注意,正如某些Win32数据结构所做的那样,您可以在结构中使用最大大小的字符串缓冲区,例如

    struct Student
    {
        int ID;
        char Name[60];
    };
    

    在这种情况下,您可以使用像strcpy()这样的C函数或更安全的变体来将源字符串深度复制到Name缓冲区中。在这种情况下,由于名称字符串位于结构内部,因此具有良好的局部性,并且相对于原始char *指针大小写具有简化的内存管理,但代价是具有预分配的内存缓冲区。 根据您的特定编程环境,这可能是也可能不是更好的选择。无论如何,请记住,这是一种更像C的方法;更好的C ++方法是使用像std::string这样的字符串类。

答案 4 :(得分:1)

这实际上取决于您的使用案例。如上所述,您应该在C ++中使用std::string。但是如果你使用的是C风格的字符串,那么这取决于你的用法。

使用定义大小的 char [] ,可以避免因空指针和其他指针相关错误(如内存泄漏,悬空指针等)导致的错误,但您可能无法充分利用内存。例如,您可以定义

#define MAX_SIZE 100
struct student
{
    int ID;
    char name[MAX_SIZE];
};

然后

#define STUDENT_COUNT 50
struct student many_students[STUDENT_COUNT];

但是学生姓名的长度会有所不同,在很多情况下远远小于MAX_SIZE。因为这样大量的记忆将被浪费掉。 或者在某些情况下,它可能大于MAX_SIZE。您可能必须在此处截断名称以避免内存损坏。

在我们定义使用 char * 的其他情况下,由于我们只分配了所需的数量,因此不会浪费内存,但我们必须注意内存分配和释放。

struct student
{
    int ID;
    char *name;
};

然后在存储名称时我们需要做这样的事情:

struct student many_student[STUDENT_COUNT];
int i;
for( i=0; i<STUDENT_COUNT; i++) {
    // some code to get student name
    many_student[i].name = (char*)malloc(name_length+1 * sizeof(char));
    // Now we can store name
}

// Later when name is no longer required free it
free(many_student[some_valid_index_to_free].name);
// also set it to NULL, to avoid dangling pointers
many_student[some_valid_index_to_free].name = NULL;

此外,如果您再次为name分配内存,则应释放先前分配的内存以避免内存泄漏。另外要考虑的是在使用之前对指针进行NULL检查,即,您应该始终检查为

if(many_students[valid_index].name!=NULL) {
    // do stuff
}

虽然您可以创建宏来执行此操作,但这些是指针的基本开销。

使用指针的另一个好处是,如果有许多相似的名称,那么你可以将多个指针指向同一个名称并节省内存,但是在数组中你将为所有人提供单独的内存,例如,

// IF we have a predefined global name array
char *GLOBAL_NAMES[] = {"NAME_1", "NAME_2", "NAME_3", "NAME_4", ... , "NAME_N"};


// using pointers, just need to assign name to correct pointer in array
many_student[valid_index_1].name = GLOBAL_NAMES[INDEX_NAME_1];
many_student[valid_index_2].name = GLOBAL_NAMES[INDEX_NAME_1];

// In case of array we would have had to copy.

虽然这可能不是你的情况,但只是说指针可能有助于避免额外使用。

希望它会对你有所帮助:)。

答案 5 :(得分:1)

使用 std :: string 库。它更容易使用。并且与内置对应物相比具有更多功能。