类中的字符串数组输出后程序卡死??为什么

#include <stdio.h>
#include <iostream>

using namespace std;

class CStr {
public:
    CStr(const char* pszTest) {
        if (NULL != pszTest) {
            int nLen = strlen(pszTest);
            m_pszTest = new char[nLen + 1];
            
            strcpy_s(m_pszTest,  nLen+1 , pszTest);
        }
        else {
            m_pszTest = new char[1];
            m_pszTest[0] = '\0';
        }
    }
    ~CStr() {
        if (NULL != m_pszTest) {
            delete[] m_pszTest;
            m_pszTest = NULL;
        }
    }
    
    void Show() {
        if (NULL != m_pszTest) {
            cout<<m_pszTest<<endl;
        }
    }

private:
    char *m_pszTest;
};

void TestFun(CStr s) {
    s.Show();
}

int main(  ) {
    CStr objS("TTs");
    TestFun(objS);
}

为什么这里程序会卡死,而且析构函数被调用了两次?

阅读 2.6k
1 个回答

void TestFun(CStr s) ,这里的参数不是一个引用,因而参数传递的时候会发生一次拷贝,sobjS 会是两个不同的对象。

CStr 没有自定义拷贝构造函数,所以使用默认,m_pszTest 这个指针被拷贝了一份。

然后,sobjS 都需要析构,于是析构两次。

每次析构,都会 delete[] m_pszTest; 。由于 sobjS 是两个不同的对象,将s.m_pszTest 赋值为 NULL 并不会影响 objS.m_pszText (反之也是一样)。而 s.m_pszTestobjS.m_pszTest 的值原来是相同的(来自拷贝),于是这个地址被 delete[] 两次,引发未定义行为。

改成 void TestFun(CStr &s) 就好了,引用参数不发生拷贝。

==============
你这个类实际需要提供一个自定义的拷贝构造与自定义的赋值运算符,以保证在发生拷贝的时候不只是拷贝的指针的值,以避免重复 delete 。另见rule of three

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题