C ++:在类构造函数中初始化chars数组和int

时间:2012-02-01 19:26:20

标签: c++

我正在寻找指南,甚至找到了this,但它没有提供答案。 我的问题是如何在构造函数中初始化C数组?下面我假设一个我想做的假设的例子,但是我不知道它是否可以但是有缺陷,完美,或者只是有一些错误,并且有办法让它变得更好。

class A{
private:
    char* a;
    int b;
public:
    A(char*, int);
}

A::A(char* _a, int _b){
    strcpy(a, _a);
    b = _b
}

int main(){
    A tempA;
    char arr[50];
    int c = 40;

    strcpy(arr,"derp")
    tempA = new A(arr,c)

    return 0;
}

此刻我没有C ++专家,所以我希望收到尽可能多的反馈意见。如果这是一个重复的问题,也很抱歉,但我在那里找不到任何内容。

4 个答案:

答案 0 :(得分:4)

如果要存储字符串,可以存储std::string

class A{
private:
    std::string a;
    int b;
public:
    A(std::string const&, int);
}

A::A(std::string const& _a, int _b) : a(_a), b(_b) {}

如果你的教练坚持你将字符指针视为字符串,那么你手上就有一个复杂的问题,因为你必须处理管理字符所指向的内存,以免你最终{{3} }。换句话说,您需要实现类似于std::string的内容。

所以,假设你真的需要这样做......

  • 每当您使用new时,您需要匹配delete来释放由new分配的内存;
  • 您可能希望类的构造函数调用new;
  • 如果使用具有正确析构函数的类的自动存储持续时间的对象来清理,您可以自动为您完成delete;
  • 该类可以是不可复制的(例如,通过制作私有复制构造函数和复制赋值运算符),或者如果您编写leaking memoryproper copy constructor,则可以复制;
  • 您可以使用std::copy算法轻松制作副本,或者,如果由于任意原因受到限制,您可以使用旧的memcpystrcpy功能。

这不是很简单,但如果你这样做,你会有一个非常方便的课程,可以自动管理你的记忆,让你可以专注于其他问题。

答案 1 :(得分:1)

如果需要使用c-string(字符数组),可以使用while循环。还请记住,C ++中的引用字符串(例如:“test”)是c-string而不是字符串。

class A
{
private:
    char* a;
    int b;
public:
    char * get() {return a;}
    A(char*, int);
    A();
};

A::A(char* _a, int _b)
{
    int i=0, lenth=0;
    while(_a[i++])
        lenth++;
    a= new char[lenth+1];
    i=0;
    while(_a[i])
    {
        a[i]=_a[i];  
        i++;
    }
    a[i]=_a[i]; 

    b = _b;
}

int main()
{
    A *tempA;
    char arr[50];
    int c = 40;

    strcpy(arr,"test string");
    tempA = new A(arr,c);
    cout << tempA->get();

    return 0;
}

答案 2 :(得分:1)

我认为这是一个练习,你正在尝试创建自己的字符串类。实际上,我认为这是一个很好的练习。实际上这非常困难。

无论如何,一旦你需要了解C ++的事情就是“所有权”。在这种情况下,您的A类将拥有它分配的内存,并将负责以后删除它。

您需要使用new[]分配内存。然后您必须稍后使用delete[]将其删除。后者将在A的析构函数中完成。

class A
{ 
  private:     
      char* a;     
      int b; 

  public:     
      A(const char*, int); 
      ~A();

};

A::A( const char * a_, int b_ )
 : a( new char[b_+1], b( b_ )
{
    strncpy( a, a_, b ); // could also use memcpy which would allow embedded nulls,
         // in which case you must also add the null terminator yourself.
}

A::~A()
{
    delete[] a;
}

我假设创建类的用户将字符串的长度作为第二个参数传递,因此您的类必须是智能的,以便为null终止符分配额外的字符

您的课程尚未完成。你需要处理: - 用户将如何读回字符串。 - 复制你的课程 - 指派你的班级。

请注意,您将获得一个自动生成的副本和分配,它将复制并分配您班级的每个成员。问题是你现在有两个实例持有相同的指针,它们都会尝试删除它。另外,被分配的类已经有一个需要删除的指针,这个指针最终会在空间中丢失(内存泄漏)。

我不打算为你解答,因为你的练习是找出如何处理这种情况。

答案 3 :(得分:0)

strcpy(a, _a)将无法执行您想要的操作:它假定a已经指向一些足够大的内存以包含_a中的内容,而事实并非如此。

这是对当前代码的最小更改:

A::A(char *_a, int _b)
{
  a = strdup(_a); // makes a copy
  b = _b;
}

更惯用:使用初始化列表,并承诺我们不会修改传入的数组(注意const):

A::A(char const *_a, int _b)
  : a(strdup(_a)), b(_b)
{
  // all the work was done above
}

一般来说,使用std::string会更好的C ++风格,让它为你担心内存:

class A
{
  std::string a;
  int b;
public:
  A(char const *_a, int _b) : a(_a), b(_b) {}

  // we can provide two versions, so you can pass in a std::string as well
  A(std::string const &_a, int _b) : a(_a), b(_b) {}
};

由于无法使用std::string进行此分配,因此您无需免费获取内存管理,因此需要编写析构函数:

A::~A()
{
  free(a);
}

否则当A的实例死亡时,您复制的char *数组将被泄露。顺便提一句,你问题中的代码会泄漏整个A对象。