【问题标题】:C++ pointer to new memory storing gibberish指向存储乱码的新内存的 C++ 指针
【发布时间】:2013-08-15 04:30:28
【问题描述】:

我有一个接受字符数组的类。我意识到 std::string 更适合处理字符串,但这是学习指针和分配动态内存的练习。 我遇到的问题是重载的加法运算符。我将新内存分配给连接的两个 char 数组的大小,加上一个终止的空字符。当我在 for 循环上设置断点时,我可以看到程序正在遍历左侧操作数指针 (p),然后是右侧操作数指针 (q),但各个字符并未存储到 temp_str。

我对 C++ 相当陌生,所以我确信我缺少一些关于指针和/或动态内存的基本知识。任何帮助/建议将不胜感激。谢谢。

#include <iostream>
#include <cstring>
using std::cout;
using std::endl;

class CStr
{
private:
    int m_length;
    char* m_pstr;

public:
    // Constructor
    CStr (const char* s = "Default String")
    {
        cout << "Constructor called\n";
        m_length = strlen(s) + 1;           // Store the length of the string
        m_pstr = new char[m_length];        // Allocate space for the string
        strcpy_s(m_pstr,m_length,s);        // Copy string to memory
    }

    // Copy constructor
    CStr (const CStr& aStr)
    {
        cout << "Copy constructor called\n";
        m_length = aStr.m_length;                   // Get length of the object to be copied
        m_pstr = new char [m_length];               // Allocate space for the string
        strcpy_s(m_pstr, m_length, aStr.m_pstr);    // Copy string to memory
    }           

    // Assignment operator
    CStr& operator=(const CStr& aStr)
    {
        cout << "Assignment operator called\n";

        if(this == &aStr)                               // Check addresses, if equal
        return *this;                               // return the 1st operand

        m_length = aStr.m_length;                           // Get length of the rhs operand

        delete [] m_pstr;                               // Release memory for the lhs operand
        m_pstr = new char[m_length];                        // Allocate space for the string

        strcpy_s(m_pstr, m_length, aStr.m_pstr);        // Copy rhs operand string to the lhs operand

        return *this;                                       // Return a reference to the lhs operand
    }  

    // Addition operator
    CStr operator+(const CStr& aStr) const
    {
        cout << "Addition operator called\n";

        // get the lengths of the strings
        size_t rhs_length = strlen(aStr.m_pstr);                    // length of rhs operand
        size_t lhs_length = strlen(this->m_pstr);                   // length of lhs operand

        char* temp_str = new char[lhs_length + rhs_length + 1];     // Allocate memory to hold concatenated string
                                                                    // plus terminating null character
        char* p = this->m_pstr;
        char* q = aStr.m_pstr;

        for (p; *p!=0; p++)             // Increment lhs string pointer 
            *temp_str++ = *p;           // Store character

        for (q; *q!=0; q++)             // Increment rhs string pointer
            *temp_str++ = *q;           // Store character

        *temp_str++ = '\0';             // Null character at the end

        return CStr(temp_str);
    }

    // Destructor
    ~CStr ()
    {
        cout << Print() << " has been destroyed\n";
        delete [] m_pstr;                               // Free memory assigned to the pointer
    }

    // Print function
    char* Print() const
    {
        return m_pstr;
    }
};

int main()
{
    CStr s1("foo");
    CStr s2("bar");

    CStr s3 = s1 + s2;
}

【问题讨论】:

  • 首先,您的复制构造函数和复制赋值运算符都没有设置m_length 字段。
  • 你为什么有一个成员,里面存储了字符串的长度,你不使用。在所有功能中,您调用 strlen();
  • 将 operator+ 声明为独立的二进制函数会更好。
  • 编辑了复制构造函数和复制赋值运算符以使用m_length 成员

标签: c++ pointers dynamic char


【解决方案1】:

在复制操作中,您正在执行temp_str++ 直到temp_str 指向您分配的数组之外,因此返回的CStr(temp_str) 也指向它之外。

您可以通过在复制循环中使用单独的指针或在返回之前从temp_str 中减去您存储的字符数来轻松解决此问题。

【讨论】:

    【解决方案2】:

    operator+ 函数有一个大问题:你从一个指向字符串之外的指针创建了一个字符串。

    当您增加temp_str 指针时,您会丢失原始指针,因此当您执行return CStr(temp_str) 时,指针指向字符串的终止符之外。

    与其手动将字符串复制到新内存中,不如简单地使用例如memcpytemp_str 以及目标的可能偏移量:

    memcpy(temp_str, p, lhs_length);
    memcpy(temp_str + lhs_length, q, rhs_length);
    temp_str[lhs_length + rhs_length] = '\0';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-28
      • 2015-05-19
      • 1970-01-01
      • 2012-09-25
      • 1970-01-01
      相关资源
      最近更新 更多