C++ c++;这个问题的问题在哪里?(带参数的构造函数)
假设string类有如下私有数据成员:C++ c++;这个问题的问题在哪里?(带参数的构造函数),c++,C++,假设string类有如下私有数据成员: char *strval; int length; string::string(const char* s):length(strlen(s)) { strval = s; } 字符串类的以下构造函数代码正确吗?如果不正确,原因是什么? char *strval; int length; string::string(const char* s):length(strlen(s)) { strval = s; } 我的回
char *strval;
int length;
string::string(const char* s):length(strlen(s))
{
strval = s;
}
字符串类的以下构造函数代码正确吗?如果不正确,原因是什么?
char *strval;
int length;
string::string(const char* s):length(strlen(s))
{
strval = s;
}
我的回答是strlen()正在计算指针值,但这听起来是错误的。给出的构造函数代码是正确的,因为它将为大多数输入成功编译和运行。然而,它的风格很差,至少有几个原因:
- 一个成员使用初始化器列表初始化,而另一个成员在构造函数中分配(这是不一致的)
- 未检查
是否为s
(但这可能被记录为非法输入)NULL
- 如果不制作字符串的副本,则单独存储指针和长度是多余的(因为它们可能会不同步)
- 一个成员使用初始化器列表初始化,而另一个成员在构造函数中分配(这是不一致的)
- 未检查
是否为s
(但这可能被记录为非法输入)NULL
- 如果不制作字符串的副本,则单独存储指针和长度是多余的(因为它们可能会不同步)
strval=s
将失败,因为strval
是指向const
的指针,而s
不是。以下是一个更好的起点:
class string
{
const char *strval; // This must be const for 'strval = s' to work.
int length;
string (const char *s);
};
string::string(const char* s):length(strlen(s))
{
strval = s;
}
@格雷格的观点仍然有效。我只是强调一个要点。代码不正确,甚至无法编译
strval=s
将失败,因为strval
是指向const
的指针,而s
不是。以下是一个更好的起点:
class string
{
const char *strval; // This must be const for 'strval = s' to work.
int length;
string (const char *s);
};
string::string(const char* s):length(strlen(s))
{
strval = s;
}
@格雷格的观点仍然有效。我只是强调一个要点。字符串可能有三种合理的工作方式,但正如前面介绍的,它不属于这三种类型中的任何一种。它们是:
std::string
does(常量字符*,长度)
常量
“参考”指的是
调用者,这保证了
文本的生存期将长于
“字符串”的用法(字符*,长度)
参考
服务器拥有的可写缓冲区
调用者,但“字符串”插入其中
对象可能会进行更新(可能是
即使移动NUL终结者)int length; // should really be size_t
char *strval;
…以便构造函数可以使用初始化列表,并知道将首先填充长度值,因此可用于strval的初始化-这消除了两次计算字符串长度的需要
string(const char* p, int n)
: length(strlen(p)), strval(new char[length + 1])
{
strcpy(strval, p);
}
2.对文本的不断引用
如果字符串不是一般用途的字符串,那么它的第一个也是最大的问题就是名称“string”。为了得到一个更好的名称,让我们回到介绍的功能。它记住调用者指定的缓冲区的地址和当前内容长度:根据我的经验,这通常是在指针为常量时完成的——例如,在调用者的字符缓冲区中抽象非NUL终止的子字符串——例如,内存映射文件中的元素位置
Aaron首先发现的第二个问题是,构造函数的字符串参数是const
,需要简单地更改为char*
,以允许从中初始化strval
。或者,如果您将strval
更改为const char*
,我们将返回到前面提到的const
非NUL终止子字符串引用。同样,应该找到合适的名称,例如text\u reference
,substring\u reader
或任何适合您的名称
3.对文本的非常量引用
显示的strval
指针不是const
,它表示一个对象能够覆盖提供的缓冲区的内容,但仍然不能延长缓冲区。这在我的经验中很少有用,尽管它可能非常适合某些特定项目的需要。应该为这样的类找到更好的名称,这并不容易!,但是,例如“缓冲区覆盖器”提示——至少在我看来——长度上限和非constaccess。此外,所提供的构造函数仅适用于已经以NUL终止的缓冲区,但我们可以想象第二个构造函数(char*,int)
,它删除了该要求,并可能使对象更广泛地有用
否则,Greg将覆盖t