C struct中的c ++字符串,是非法的吗?

时间:2010-09-30 05:42:33

标签: c++

struct run_male_walker_struct {
        string male_user_name;
        string show_name;
};
typedef struct run_male_walker_struct run_male_walker_struct_t;

在另一个函数中:

run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct));
问题,这是非法的吗?由于字符串是一个类,因此无法通过sizeof()确定其大小。

8 个答案:

答案 0 :(得分:5)

不确定你在这里问的是什么......为了清楚起见,struct关键字是一个有效的C ++标识,其功能几乎与class相同,但默认隐私除外。因此,如果您正在使用g ++进行编译,并且包含字符串库,那么这是一个有效的声明。

然而,使用malloc()调用只会给你内存,而不是实际构造该结构中的值。您可以通过调用它的默认构造函数来更恰当地实例化它。

答案 1 :(得分:5)

这是非法的,但不是出于你的想法。

std::malloc() / std::free()new / delete之间的区别在于后者会调用构造函数/析构函数,而前者则不会。表达式

void* p = std::malloc(sizeof(run_male_walker_struct))

将返回未初始化的内存块,其上没有调用构造函数。你不应该用十英尺的杆子触摸它 - 除了在它上面调用一个构造函数:

run_male_walker_struct* pw = new(p) run_male_walker_struct;

如果你这样做,你也必须反过来:

pw->~run_male_walker_struct();
在释放记忆之前

std::free(p);

但是,这就留下了为什么要这样做的问题 执行此操作的唯一原因应该是您希望将内存分配与构造分开(例如,在池分配器中)。但如果你需要它,它最好隐藏在一些界面后面。一个自然的会为每个类重载newdelete 。此外,std::vector在内部执行此操作。

答案 2 :(得分:3)

结构定义本身很好。结果是非POD聚合。但是您应该优先使用newdelete而不是mallocfree,因为它们可以正确处理构造和破坏。如果你想继续使用malloc和free,你必须使用placement-new来正确构造对象,并在释放它之前手动调用析构函数来销毁它:

#include <new>
...
run_male_walker_struct *p = (run_male_walker_struct*)
    malloc(sizeof(run_male_walker_struct));
new(p) run_male_walker_struct; // <-- placement-new
...
p->~run_male_walker_struct(); // <-- pseudo destructor call
free(p);

或者简单地说:

run_male_walker_struct *p = new run_male_walker_struct;
...
delete p;

BTW:在C ++中不需要typedef

答案 3 :(得分:2)

如果您使用的是C ++,请尽量不要使用malloc。 使用NEW是一个更好的选择,当你浏览NEW()代码时,你会意识到它会调用malloc !!!

使用NEW的优点是它将调用类实例化的构造函数。

另一个小评论,您提供的代码不应该是可编辑的:

run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct));

应该是

run_male_walker_struct_t *p = (run_male_walker_struct_t*)malloc(sizeof(struct run_male_walker_struct));

这是由于malloc将返回void *。

答案 4 :(得分:1)

使用malloc()可以工作,但使用它只会为你的struct创建足够的空间。 这意味着您将无法正确使用字符串,因为它们未使用其构造函数进行初始化。

请注意,字符串类的内容不在堆栈内存中,而是在动态内存中,这不会影响结构的大小。所有类和结构都具有静态大小,这在编译时是已知的(如果定义了struct / class)。

我建议使用新的。使用malloc 填充字符串。

这提出了我自己的问题,如何在C中动态分配实例化调用构造函数(C中是否没有构造函数?)。如果是这样,反对使用纯C的另一个原因。

答案 5 :(得分:1)

我很确定这是合法的,因为即使字符串的长度未知,std :: string对象的大小也是已知的。结果可能不是您所期望的,因为malloc不会调用构造函数。

试试这个:

std::string testString1("babab");
std::string testString2("12345678");
std::string testString3;
std::cout <<" sizeof(testString1)" <<sizeof(testString1) << std::endl;
std::cout <<" sizeof(testString2)" <<sizeof(testString2) << std::endl;
std::cout <<" sizeof(testString3)" <<sizeof(testString3) << std::endl;

在我的机器上,这给了我以下输出:

 sizeof(testString1)8
 sizeof(testString2)8
 sizeof(testString3)8

还有一些原因你没有使用:

run_male_walker_struct_t *p = new(struct run_male_walker_struct);

这是在c ++中使用它的正确方法,使用malloc几乎肯定是一个错误。

编辑:有关c ++中new vs malloc的更详细说明,请参阅此页面: http://www.codeproject.com/KB/tips/newandmalloc.aspx

答案 6 :(得分:1)

怎么样

run_male_walker_struct_t * p = new run_male_walker_struct_t:

答案 7 :(得分:1)

答案取决于“C结构”的含义。

如果您的意思是“在C语言下有效的结构”,那么答案显然是:它包含的数据类型无效C,因此结构本身也无效。

如果你的意思是C ++ POD类型,那么答案是否定的,它不是非法的,但结构不再是POD类型(因为为了成为POD,它的所有成员也必须是POD,并且{ {1}}不是)