我在初始化char* a = new char[size]
时遇到问题。这是我的代码。
class Practice
{
public:
Practice(const char* a);
~Practice();
const char* getString() const;
private:
char* mString;
int mSize;
};
#include "Practice.h"
Practice::Practice(const char * a)
:mSize(0)
,mString(nullptr)
{
while (a[mSize] != '\0')
{
mSize++;
}
mString = new char[mSize];
for (int i = 0; i < mSize; i++)
{
mString[i] = a[i];
}
}
Practice::~Practice()
{
delete[] mString;
}
const char* Practice::getString() const
{
return mString;
}
int main()
{
Practice p("Hello");
std::cout << p.getString() << std::endl;
return 0;
}
我希望结果是Hello
。
但是结果就像Hello²²²²▌▌▌▌▌▌▌■a%{▌
。
我以为我通过mString
初始化了mString = new char[mSize]
成员变量。但这没有按照我的想法工作。
有人能启发我我的代码有什么问题并修复它吗?
答案 0 :(得分:5)
mString
不是NUL终止的。
答案 1 :(得分:1)
您正在检查a
的{{1}}构造函数参数。但是您没有分配\0
来放置相同的mString
,也不要从\0
复制\0
。
因此,生成的a
不能正确地以NULL结尾,并且将被读取到结尾。
读取超出分配的末尾是未定义的行为。在特定情况下,很可能mString
会一直输出直到意外的零,否则会发生崩溃。
答案 2 :(得分:1)
while (a[mSize] != '\0') { mSize++; }
这将mSize
设置为等于a
的长度,但不包括结尾的'\0'
。您应该在副本中包含终止符:
while (a[mSize++])
{
}
或简单地:
mSize = strlen(a) + 1;
答案 3 :(得分:0)
您并没有将mString
数据终止于null,但是当您将其传递给std::cout
时,它有望被终止于null。如果没有该终结符,std::cout
会读入周围的内存,直到遇到随机的空字节(或由于读取访问错误而崩溃)。这就是为什么您看到std::cout
在数据之后输出随机垃圾的原因。
您还没有遵循Rule of 3/5/0,因为您缺少默认构造函数,复制和移动构造函数以及复制和移动分配运算符。
尝试一下:
class Practice
{
public:
Practice(const char* a = nullptr);
Practice(const Practice &src);
Practice(Practice &&src);
~Practice();
Practice& operator=(Practice src);
const char* getString() const;
private:
char* mString;
int mSize;
};
#include "Practice.h"
#include <utility>
Practice::Practice(const char * a)
: mSize(0)
, mString(nullptr)
{
if (a)
{
while (a[mSize] != '\0')
{
++mSize;
}
}
mString = new char[mSize + 1];
for (int i = 0; i < mSize; ++i)
{
mString[i] = a[i];
}
mString[mSize] = '\0';
}
Practice::Practice(const Practice &src)
: mSize(src.mSize)
, mString(nullptr)
{
mString = new char[mSize + 1];
for (int i = 0; i < mSize; ++i)
{
mString[i] = src.mString[i];
}
mString[mSize] = '\0';
}
Practice::Practice(Practice &&src)
: mSize(src.mSize)
, mString(src.mString)
{
src.mString = nullptr;
src.mSize = 0;
}
Practice::~Practice()
{
delete[] mString;
}
Practice& Practice::operator=(Practice src)
{
std::swap(mString, src.mString);
std::swap(mSize, src.mSize);
return *this;
}
const char* Practice::getString() const
{
return mString;
}
#include <iostream>
#include "Practice.h"
int main()
{
Practice p("Hello");
std::cout << p.getString() << std::endl;
return 0;
}