简体   繁体   中英

initializing char* a = new char[size] does not work

I have a problem about initializing char* a = new char[size] . Here is my code.

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;
}

I expected the result is Hello .

But the result was like Hello²²²²▌▌▌▌▌▌▌■a%{▌ .

I thought I initialized the mString member variable through mString = new char[mSize] . But it was not working the way I thought.

Can anybody enlighten me what's wrong with my code and fix it?

mString不是以 NUL 结尾的。

Your're checking a constructor parameter for \\0 . But you are not allocating mString to put the same \\0 there, and don't copy \\0 from a .

So, resulting mString is not properly NULL-terminated and it would be read beyond end.

Reading beyond end of allocated is undefined behavior. In particular case, it is likely that either mString would output until some accidental zero, or crash would occur.

while (a[mSize] != '\\0') { mSize++; }

This sets mSize equal to the length of a , excluding the terminating '\\0' . You should include the terminator in your copy:

while (a[mSize++])
{
}

or simply:

mSize = strlen(a) + 1;

You are not null-terminating your mString data, but it is expecting to be null-terminated when you pass it to std::cout . Without that terminator, std::cout reads into surrounding memory until it encounters a random null byte (or crashes with a read access error). That is why you are seeing std::cout output random garbage after your data.

You are also not following the Rule of 3/5/0 , as you are missing a default constructor, copy and move constructors, and copy and move assignment operators.

Try this:

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM