我尝试读取一个文件,用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
先谢谢你:-)
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){
...
}
这个问题就会消失。