使用传入数组初始化其他数组

时间:2017-04-21 00:17:35

标签: c++ arrays memory strcpy

我正在尝试“初始化”我在班级声明中制作的数组,但我不知道我做错了什么。我知道当你将一个数组传递给一个函数时,它会衰减成一个指向第一个字符的指针。代码在我的第二个strcpy()行中断,但我不确定它是做错了(我对strcpy()的经验很少。)

我的代码如下:

class TestClass
{
public:
    TestClass(char []);
    ~TestClass();
    void Append(TestClass);

    char* m_string;
};

TestClass::TestClass(char incstring[])
{
    char currentChar = 'a';
    int numOfChars = 0;

    while (currentChar != '\0') {
        currentChar = *(incstring + numOfChars);
        numOfChars++;
    }

    char* tmp = new char[numOfChars-1];
    strcpy(tmp, incstring);
    strcpy(m_string, tmp);
}

我的int main()很简单:

int main(){
    TestClass* test = new TestClass("Hello");
}

如果值得注意,numOfChars等于6,正确应该是。

抛出的异常是:“访问冲突写入位置0xCDCDCDCD。”

1 个答案:

答案 0 :(得分:2)

在将数据从m_string复制到tmp之前,您没有为m_string分配任何内存。这就是你崩溃的原因。 m_string未指向有效的内存地址。

由于您已经分配了tmp并且您不再使用它,因此您可以直接将tmp指针指定给m_string,而无需执行其他副本。

另请注意,您的while循环正在重复strlen()已经执行的操作,因此您应该只使用strlen()

试试这个:

TestClass::TestClass(char incstring[])
    : m_string(new char[strlen(incstring)+1])
{
    strcpy(m_string, incstring);
}

TestClass::~TestClass()
{
    delete[] m_string;
}

可以使用strdup()来简化(使用free()代替delete[]来解除分配):

TestClass::TestClass(char incstring[])
    : m_string(strdup(incstring))
{
}

TestClass::~TestClass()
{
    free(m_string);
}

话虽如此,你的main()正在泄漏内存,因为你没有释放test对象:

int main(){
    TestClass* test = new TestClass("Hello");
    //...
    delete test; // <-- add this
}

或者简单地说:

int main(){
    TestClass test("Hello");
}

最后,请务必在班级中实施Rule of Three。您正在管理在析构函数中释放的动态内存,因此在从其他m_string值创建TestClass值时,您还需要复制构造函数和复制赋值操作以确保TestClass的完整性:

class TestClass
{
private:
    char* m_string;

public:
    TestClass(char *incstring = 0);
    TestClass(const TestClass &src);
    ~TestClass();

    void Append(const TestClass &str);
    void Swap(TestClass &Other);

    TestClass& operator=(const TestClass &lhs);
};

TestClass::TestClass(char *incstring)
    : m_string(0)
{
    if (incstring)
    {
        m_string = new char[strlen(incstring)+1];
        strcpy(m_string, incstring);
    }
}

TestClass::TestClass(const TestClass &src)
    : m_string(0)
{
    if (src.m_string)
    {
        m_string = new char[strlen(src.m_string)+1];
        strcpy(m_string, src.m_string);
    }
}

TestClass::~TestClass()
{
    delete[] m_string;
}

void TestClass::Append(const TestClass &str)
{
    if (str.m_string)
    {
        TestClass tmp;
        tmp.m_string = new char[strlen(m_string)+strlen(str.m_string)+1];
        strcpy(tmp.m_string, m_string);
        strcat(tmp.m_string, str.m_string);
        Swap(tmp);
    }
}

void TestClass::Swap(TestClass &Other)
{
    char *ptr = m_string;
    m_string = Other.m_string;
    Other.m_string = ptr;
}

TestClass& TestClass::operator=(const TestClass &lhs)
{
    if (this != &lhs) {
        TestClass(lhs).Swap(*this);
    }    
    return *this;
}