1

这是一种伪代码,但它应该清楚我想知道的内容。我在不同的代码中看到了所有 3 个变体。

我的问题是这样做的正确方法是什么,为什么?(另见代码片段中的注释)

test.h 第一种方式:

class Test {
    public:
        Test() 
            :_buffer(NULL)
         {
            _buffer = new char[1024];
        }

        ~Test() {
           delete _buffer;
        }

        int Function() {
           //use some function like inet_ntop doesn't work _buffer is not filled
           inet_ntop(p->ai_family, addr, _buffer,  sizeof(_buffer)-1);
           //here sizeof(_buffer) returns 4, WHY ?
           cout << sizeof(_buffer) << endl;
        }

    private:
        char *_buffer;
};

test.h 第二种方式:

class Test {
    public:
        Test() {
            //_buffer is never initialized WHY ?
        }
        ~Test() {
           //_buffer is never deleted WHY ?
        }
        int Function() {
           //use some function like inet_ntop works correctly here _buffer is filled 
           inet_ntop(p->ai_family, addr, _buffer,  sizeof(_buffer)-1);
           //here sizeof(_buffer) returns 1024, WHY ?
           cout << sizeof(_buffer) << endl;
        }
     private:
         char _buffer[1024];
};

test.h 第三种方式:

class Test {
    public:
        Test() {
        }
        ~Test() {
        }
        int Function() {
           char buffer[1024];
           //use some function like inet_ntop works correctly here _buffer is filled
           inet_ntop(p->ai_family, addr, _buffer,  sizeof(_buffer)-1);
           //here sizeof(_buffer) returns 1024
           cout << sizeof(_buffer) << endl;
        }
     private:
};
4

3 回答 3

6

C++ 在类中声明 char 数组的正确方法是什么?

两者都不。
在 C++ 中,正确的方法是使用:

std::string buffer;

这正是 C++ 提供std::string. 它使您可以自由:

  • 显式管理内存,如#1&
  • 覆盖静态分配数组的边界,如#2.

请注意,您展示的 3 个示例并不相同。
#1&#2将字符缓冲区的生命周期绑定到您的对象实例,
而 While#3不这样做。

请注意,如果您需要一个本地缓冲区(其大小是固定的)只是为了传递给 c 风格的 api,那么这种用法并不能很好地利用所提供的好东西,std::string并且可能静态分配的字符数组更合适。

如果您的要求与 in 一样#1#2那么当然是更好的选择std::string

于 2013-01-13T07:53:46.693 回答
2

第一种变体:字符数组是从堆中分配的。IIRC,析构函数中的删除应该是delete [] _buffer.

第二种变体:字符数组是类的一部分,与类一起生死。可以从堆或堆栈中分配,具体取决于类的实例化方式。

第三种变体:字符数组在堆栈上分配,并在封闭范围(在本例中为Function())结束时释放。

话虽如此,除非您出于正当理由确实需要一组字符,否则使用std::string要好得多。

于 2013-01-13T07:57:42.327 回答
2

我不相信您正在尝试做的事情有“一种真正的方式”。每种方法都涉及权衡。具体来说:

方法1)你在堆上分配内存。您会受到(轻微的)性能损失。但是,您的类在内存中的大小会减少。如果你在堆栈上分配你的类,你会浪费更少的堆栈空间。正如其他人所提到的,您需要使用该delete []语句。

关于您的评论, sizeof(buffer) 返回 4 因为 buffer 是一个字符指针。您的平台将指针定义为 4 字节大。它不报告已分配数组的大小,因为 sizeof 适用于对其描述的类型。inet_ntop 没有填满你的缓冲区,因为你告诉它你的缓冲区只有 4 个字节大。inet_ntop 只是失败了,因为该缓冲区非常小。

方法 2)这用方法 1 的额外堆分配来增加类大小。

关于注释,缓冲区没有被初始化或删除,因为 C++ 处理它。由于您指示编译器为您提供大小为 1024 字节的 char 数组,因此它为您提供了一个。您不需要为编译器初始化/清理。此外,sizeof 返回 1024,因为类型是 1024 字节的 char 数组,因此编译器知道这一点并给出数组大小。它不会在这里返回指针的大小,因为您没有要求指针。

方法3)这个方法改为每次调用函数时分配缓冲区,并将其放入堆栈。根据您打算如何处理数据,这可能是最佳解决方案,或者根本不适用。如果函数结束后不需要缓冲区,那么它是一个不错的选择。

于 2013-01-13T08:13:15.567 回答