这是一种伪代码,但它应该清楚我想知道的内容。我在不同的代码中看到了所有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:
};
答案 0 :(得分:6)
C ++在类中声明char数组的正确方法是什么?
都不是。
在C ++中,正确的方法是使用:
std::string buffer;
这正是C ++提供std::string
的原因。它让你自由:
#1
&amp; #2
。请注意,您显示的3个示例并不等效
#1
&amp; #2
将字符缓冲区的生命周期绑定到对象实例,
虽然#3
没有做同样的事情。
请注意,如果你需要一个本地缓冲区(,其大小是固定的)只是为了传递给c风格的api,那么这种用法并不能很好地利用{{{ 1}}并且可能静态分配的字符数组更合适。
如果您的要求与std::string
和#1
相同,那么更好的选择是#2
。
答案 1 :(得分:2)
第一个变体:从堆中分配字符数组。 IIRC,析构函数中的删除应为delete [] _buffer
。
第二个变体:字符数组是类的一部分,并且与类一起生存和死亡。可以从堆或堆栈中分配,具体取决于实例化类的方式。
第三种变体:字符数组在堆栈上分配,并在封闭范围(在本例中为Function()
- 结束时)释放。
话虽如此,除非你确实需要一个正确理由的字符数组,否则使用std::string
要好得多。
答案 2 :(得分:2)
我不相信你想要做的事情有“一种真正的方法”。每种方法都涉及权衡。具体做法是:
方法1)在堆上分配内存。您会受到(轻微)性能损失。但是,内存中类的大小会减少。如果在堆栈上分配类,则会以这种方式浪费更少的堆栈空间。正如其他人所提到的,您需要使用delete []
语句。
关于你的注释,sizeof(buffer)返回4,因为buffer是一个char指针。您的平台定义指针为4字节大。它不会报告已分配数组的大小,因为sizeof适用于所描述的类型。 inet_ntop没有填充你的缓冲区,因为你告诉它你的缓冲区只有4个字节大。 inet_ntop只是失败,因为缓冲区很小。
方法2)这将交换方法1的额外堆分配以增加类的大小。
关于注释,缓冲区未初始化或删除,因为C ++处理它。由于您指示编译器为您提供大小为1024字节的char数组,因此它为您提供了一个。您不需要为编译器初始化/清除。此外,sizeof返回1024,因为类型是1024字节的char数组,因此编译器知道这一点并给出数组大小。它不会返回指针的大小,因为你没有要求指针。
方法3)此方法每次调用函数时都会分配缓冲区,并将其放在堆栈中。根据您打算对数据执行的操作,这可能是最佳解决方案,或根本不适用。如果在函数结束后你不需要缓冲区,那么这是一个不错的选择。