代码之家  ›  专栏  ›  技术社区  ›  Germán

C++按值传递结构或对象

  •  3
  • Germán  · 技术社区  · 14 年前

    我有这个:

    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);
    

    现在一切正常。

    但是,按价值排序的结构怎么会和内存发生冲突呢?

    4 回复  |  直到 14 年前
        1
  •  2
  •   sellibitze    14 年前

    您没有提供自己的复制构造函数或赋值运算符。因此,当您进行复制或赋值时,编译器生成的复制构造函数和赋值运算符被使用,在这种情况下,它们实际上做不到正确的事情。它们只是复制每个成员,这样您最终得到两个引用 相同的 字符数组。而且两个配置对象都觉得有责任删除数组,这几乎肯定会导致“双重删除”错误。

    记住” rule of three “。这里的问题是指针的行为不符合您的要求。如果您使用了std::string作为成员,那么就不必编写自己的复制构造函数、析构函数和赋值运算符。这是因为编译器生成的操作只是对其成员调用相关操作,而字符串成员已经正确地处理了这一点——与指向char的指针不同。

        2
  •  6
  •   anon    14 年前

    使用strdup的事实表明您的代码有问题,而错误的是您没有复制构造函数。任何时候有一个析构函数,您几乎肯定也需要一个复制构造函数,当您按值调用时,它将正确地复制对象。

    要改进代码:

    • 创建一个复制构造函数,可能是一个分配运算符,用于正确分配和复制字符串。

    • 更好的是,去掉strdup-使用std:;字符串,在这种情况下,您不需要析构函数、复制ctor或赋值操作。

    • 去掉“inline”关键字——它们什么都不做。

        3
  •  1
  •   Daniel A. White    14 年前

    当你用引用调用它时,它的复制 units *name 但不是里面的值 *名称 . 所以当临时对象被破坏时,它将释放 *名称 从的所有实例 Configuration .

        4
  •  1
  •   Alexander Beletsky    14 年前

    您必须添加一个复制构造函数并处理char*名称;(意味着,分配和删除内存,用值初始化)。

    无论如何,对于字符串使用char*不是一个好主意。使用std::string,它将为您处理所有事情。