因重载操作符或内存管理问题而未正确返回char *。

问题描述 投票:0回答:1

我尝试读取一个文件,用C++解压并解析成一棵树。一切都很好,但有一点需要说明。出于某种原因,我可以构造一个char[]字符串,并在其上使用一个指针来输出它,并在一个友情重载的<<-操作符中使用cout,但不能使用操作符返回的指针来输出字符串。我想这可能与字符串内存的可见性有关,但这对我来说毫无意义,因为 "new "分配的内存应该对每个人都是可见的,因为它在程序的堆上,而不是某种对象或类的堆上。这一切听起来相当混乱,让我给你看一个简化版的源码,我很确信一切都会变得清晰(可能是我的一些非常愚蠢的错误......但我试了两天也没找到错误)。

main:

#include "dekompstream.h"

#include <iostream>

int main(void) {
    char *testString;
    DekompStream ds(nullptr, 0);

    std::cout << "TEST" << std::endl;
    testString << ds;
    std::cout << "Outside operator: " << testString << std::endl; // Fails misarably. Some weird randome memory-slice looking output

    //delete [] testString;

    return 0;   
}

dekompstream.cpp:

#include "dekompstream.h"

DekompStream::DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes) {
}

DekompStream::~DekompStream() {
}

uint8_t *DekompStream::dekompremieren() {
    char *test = new char[4];

    test[0] = 'A';
    test[1] = 'B';
    test[2] = 'C';
    test[3] = '\0';

    return (uint8_t *)test;
}

char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
    zeichenkette = (char *)dekompStream.dekompremieren();

    std::cout << "Inside operator: " << zeichenkette << std::endl; // Works fine

    return zeichenkette;
}

dekompstream.h:

#ifndef DEKOMPSTREAM_H
#define DEKOMPSTREAM_H

#include <cstdint>
#include <iostream>

class DekompStream {
    public:
        DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes);
        ~DekompStream(void);

        friend char *operator<<(char *zeichenkette, DekompStream &dekompStream);
    private:
        uint8_t *dekompremieren();
};

#endif

先谢谢你:-)

c++ operator-overloading
1个回答
0
投票

testString << ds 并不像你想象的那样。

如果我们看一下下面的代码 operator<<:

char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
    zeichenkette = (char *)dekompStream.dekompremieren();

    return zeichenkette;
}

该函数重新分配了 char* 参数的新值,然后返回新值。好吧 Fine. 好吧,但编译器是如何使用这个的呢?但是编译器是如何使用这个的呢?

当我们写

testString << ds;

编译器就会把它变成:

operator<<(testString, ds);

看到错误了吗?

你返回了一个新的值,但是由于操作符重载变成了函数调用,分配的指针丢失了。此外,由于 char* 参数只是被重新分配了,原来的指针值并没有改变,也就是说你得到了之前堆栈中的任何东西。

如果我们看一下iostream的STL函数的声明,我们就会发现解决这个问题的方法。

ostream& operator<< (ostream& os, const char* s);

注意第一个参数是通过引用传递的 - 这确保了函数对流的任何修改都会在调用上下文中持久存在。

只需将你的函数定义改为:

char *operator<<(char *&zeichenkette, DekompStream &dekompStream){
...
}

这个问题就会消失。

© www.soinside.com 2019 - 2024. All rights reserved.