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()确定其大小。
答案 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);
但是,这就留下了为什么要这样做的问题
执行此操作的唯一原因应该是您希望将内存分配与构造分开(例如,在池分配器中)。但如果你需要它,它最好隐藏在一些界面后面。一个自然的会为每个类重载new
和delete
。此外,std::vector
在内部执行此操作。
答案 2 :(得分:3)
结构定义本身很好。结果是非POD聚合。但是您应该优先使用new
和delete
而不是malloc
和free
,因为它们可以正确处理构造和破坏。如果你想继续使用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}}不是)