如何设计具有char *指针作为类成员变量的类?

时间:2016-03-15 19:14:50

标签: c++ memory-leaks

首先,我想介绍一下我的情况:

我已经编写了一些将char *指针作为私有类成员的类。此项目也有GUI,因此当单击按钮时,某些函数可能会执行多次。这些类设计为单个类在project.But它们的一些函数可以执行多次。然后我发现我的项目有内存泄漏。

所以我想问下列问题:

  1. 如何设计设定功能?
  2. 如何设计使用char *成员变量的其他函数?
  3. 如何设计类operator = function?
  4. 例如:

    class A:
    {
     public :
     setStr(char * s){//need new or just use =?};
     A & operator=(const A& other){//also need new?};
     manyTimesFunctions(char * other)
     {
      //need to use chars other to assignment str
      //how to carefully use new to avoid memory leak?
      //other may be another class's locality none const variable 
    
     } 
     private:
     char * str;
    }
    

    因此,该项目只启动A类一次,但可能多次使用setStrmanyTimesFunctions

    可能是答案:

    我想我已经找到了我需要照顾的事项:copy that class,答案对我来说真的很有用。

3 个答案:

答案 0 :(得分:2)

只需使用std::string即可。它为您负责内存管理。然后成员声明看起来像

std::string str;

并且setter函数看起来像

void setStr( char const* s ) { str = s; }

如果您想使用字符串并需要char const*,请写下str.c_str()

使用标准库类型(如std::string)并且没有手动动态分配,通常不需要关注operator=:编译器生成的副本分配可以很好地工作。

顺便说一下,为成员变量决定一些命名约定通常是一个好主意。 C ++的常见内容包括str_mStrmy_str。下划线后缀可能是最常见的后缀,但不要使用像_str这样的前导下划线,因为虽然技术上允许它与实现定义名称的约定冲突(例如,全局中的标识符不允许使用前导下划线)命名空间)。

答案 1 :(得分:1)

我不是100%确定你要做什么。但是,由于char *是一个指针,您可以简单地传递引用。

char* operator=(char* s) { str = s; }

只要知道,如果你修改了函数中的值,它就会修改你从

复制它的地方

如果char *实际上需要克隆,那么它不会修改原始值。首先需要获取char *的长度。

这可以通过此功能

完成
unsigned Length(char* s)
{
   unsigned I = 0;
   while( *(s+I) != '\0')
      I++;

   return I;
}

可以按如下方式创建新字符串

str = new char[LENGTH];

此时,您可以按术语

复制字符串
for(I = 0 ; I < LENGTH; I++)
{
   str[I] = s[I];
}

最后为了避免内存泄漏,需要在类析构函数

中删除它
~A()
{
    delete [] str;
}

当然使用std :: string可以节省很多问题。

答案 2 :(得分:0)

此答案将用于对比给出使用状态std::string的其他答案(并且这些答案是正确的 - 使用std::string)。

假设您只能使用char *,由于某种原因您无法使用std::string,并且您正在处理以NULL结尾的字符串。这是您的实施必须执行的操作的概要(请将其与仅使用std::string进行比较):

#include <algorithm>
#include <cstring>

class A
{
    public:
       // construct empty string
       A () : str(new char[1]()) {}

       // construct from non-empty
       A(const char *s) : str(new char[strlen(s) + 1])
       { strcpy(str, s); }

       // copy construct
       A(const A& rhs) : str(new char[strlen(rhs.str) + 1])
       { strcpy(str, rhs.str); }

       // destruct
       ~A() { delete [] str; }

       // assign
       A& operator=(const A& rhs)
       {
          A temp(rhs);
          std::swap(str, temp.str);
          return *this;
       }

       // setter
       void setStr(char * s)
       {
          A temp(s);
          *this = temp;
       }  

       // getter
       const char* getStr() { return str; }

     private:
        char * str;
};

Live Example

在添加了几个构造函数和一个getter函数之后,这将遵循Rule of 3

您看到我们需要添加多少代码才能使类安全地可复制和分配?这就是为什么使用std::string比使用char *更方便。对于std::string,与添加复制/分配(以及移动,我没有显示)功能相比,需要更改一行。

底线是在C ++中,如果你想要字符串,请使用字符串(std::string)并尽量避免使用char *(除非你有一个非常令人信服的理由使用{{1}表示字符串数据)。