【问题标题】:Using passed-in array to initialize other array使用传入的数组初始化其他数组
【发布时间】:2017-09-17 19:41:06
【问题描述】:

我正在尝试“初始化”我在类声明中创建的数组,但我不知道自己做错了什么。我知道当您将数组传递给函数时,它会衰减为指向第一个字符的指针。代码在我的第二行 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。”

【问题讨论】:

  • m_string 从未初始化。
  • 请使用std::string,省去麻烦。此外,main 中的new 没有充分的理由:TestClass test("Hello"); 在没有内存泄漏的情况下也可以做到。
  • 我刚刚将它初始化为nullptr,得到了同样的异常。
  • Kerrek 试图说明的一点是,在将数据从 tmp 复制到 m_string 之前,您没有为 m_string 分配任何内存。这就是你崩溃的原因。
  • @aschepler 我愿意,但我的规范警告我不能使用标准容器

标签: c++ arrays memory strcpy


【解决方案1】:

在将数据从tmp 复制到m_string 之前,您没有为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。您正在管理在析构函数中释放的动态内存,因此在从其他 TestClass 值创建 TestClass 值时,您还需要一个复制构造函数和一个复制赋值操作来确保 m_string 的完整性:

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

【讨论】:

    猜你喜欢
    • 2013-10-21
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多