char * 未从重载运算符或内存管理问题中正确返回

char * not returned correctly from overloaded operator or memory managment issue

我尝试读取一个文件,将其解压缩并将其解析为 C++ 中的树。一切正常,有一个例外:出于某种原因,我可以构造一个 char[] 字符串,并在它上面使用一个指针,在友好的重载 <<-operator 中的 cout 的帮助下输出它,但不能使用返回的指针运算符来计算字符串。我在想这可能与字符串内存的可见性有关,但这对我来说没有意义,因为 "new" 分配的内存应该对每个人可见,因为它在程序的堆上而不是某种对象或 class 堆。这一切听起来相当令人困惑,让我给你看一个精简版的源代码,我很确定一切都会变得清晰(可能是我这边的一些非常愚蠢的错误......但我试了两天但没有找到错误):

主要内容:

#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] = '[=11=]';

    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

提前致谢:-)

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

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

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

    return zeichenkette;
}

函数将 char* 参数重新分配给新值,然后 returns 新值。美好的。好的。但是编译器如何使用它呢?

当我们写:

testString << ds;

编译器将其转化为:

operator<<(testString, ds);

看到错误了吗?

您返回了一个新值,但由于运算符重载变成了函数调用,分配的指针丢失了。此外,因为 char* 参数被简单地重新分配,原始指针值没有改变,这意味着你得到了之前堆栈上的任何东西。

如果我们查看 iostream 的 STL 函数声明,我们将找到修复它的方法:

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

请注意,第一个参数是通过引用传递的 - 这可确保函数对流所做的任何修改都保留在调用上下文中。

只需将您的函数定义更改为:

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

问题就会消失。