我有这个:
enum Units { Pounds, Kilos };
struct Configuration
{
const Units units;
const char *name;
inline Configuration(Units pUnits, char *pName) : units(pUnits)
{
name = strdup(pName);
}
inline ~Configuration() { free((void *)name); }
};
我将其中一个传递给这样的方法:
Configuration cc(Kilos, "abc");
cdao->write(cc);
我从这里遇到了令人讨厌的崩溃,直到我尝试重新定义方法来参考:
Configuration cc(Kilos, "abc");
cdao->write(&cc);
现在一切正常。
但是,按价值结构怎么可能与内存紧密相连?
答案 0 :(得分:6)
你使用strdup的事实表明你的代码有问题,而错误的是你没有复制构造函数。每当你有一个析构函数时,你几乎肯定还需要一个复制构造函数,它会在你按值调用时正确复制对象。
改善您的代码:
创建一个复制构造函数,可能是一个正确分配和复制字符串的赋值运算符
更好的是,摆脱strdup - 使用std:;字符串,在这种情况下,你不需要析构函数,复制ctor或赋值操作。
摆脱“内联”关键字 - 它们什么都不做。
答案 1 :(得分:2)
您没有提供自己的复制构造函数或赋值运算符。因此,当您进行复制或赋值时,将使用编译器生成的复制构造函数和赋值运算符,在这种情况下实际上并不正确。它们只是复制每个成员,因此最终会有两个配置对象引用相同的字符数组。并且两个Configuration对象都有责任删除数组,这几乎肯定会导致“双删除”错误。
请记住“rule of three”。这里的问题是指针的行为不像你想要的那样。如果您使用了std :: string作为成员,则不必编写自己的复制构造函数,析构函数,赋值运算符。那是因为编译器生成的只是调用其成员的相关操作,而string-member已经正确地处理了这个 - 与指向char的指针不同。
答案 2 :(得分:1)
当您在没有引用的情况下调用它时,它会复制units
和*name
,但不会复制*name
内的值。因此,当该临时对象被破坏时,它会从*name
的所有实例中释放Configuration
。
答案 3 :(得分:1)
你必须为你的struct添加一个拷贝构造函数并处理char * name; (意思是,分配和删除内存,用值初始化)。
无论如何,对字符串使用char *是个好主意。使用std :: string,它将为你处理一切。