C+中的变量转储+; P>是否可以在C++中对复杂的结构或数组进行“转储”,以便直观地查看它们里面有什么?

C+中的变量转储+; P>是否可以在C++中对复杂的结构或数组进行“转储”,以便直观地查看它们里面有什么?,c++,data-structures,C++,Data Structures,我正在考虑类似于PHP中的print_r()或var_dump()的东西 干杯, Fin 在C++中一般不可能,因为它需要使用C++没有的反射。当然,您可以编写自己的函数来转储特定的数据结构。简短的回答是:不,除非您自己手动编写这样的例程 这通常不是一个坏主意,但如果您经常添加/更改成员,它通常会出现与类不同步的问题。这是不可避免的,因为C++在代码 S.中缺乏任何形式的内省。 如果您决定这样做,最好的办法是为std::ostream&operator编写一个重载,除了其他答案之外,还可以根据

我正在考虑类似于PHP中的print_r()或var_dump()的东西

干杯,
Fin

在C++中一般不可能,因为它需要使用C++没有的反射。当然,您可以编写自己的函数来转储特定的数据结构。

简短的回答是:不,除非您自己手动编写这样的例程

这通常不是一个坏主意,但如果您经常添加/更改成员,它通常会出现与类不同步的问题。这是不可避免的,因为C++在代码<结构> <代码> S.</P>中缺乏任何形式的内省。
如果您决定这样做,最好的办法是为
std::ostream&operator编写一个重载,除了其他答案之外,还可以根据您的需要以及是否关心可移植性,从编译器生成的调试信息中获取所需的信息。您可以从构建中解析COFF/ELF/任何格式文件,这就可以给出您需要的信息来计算对象中变量的名称和类型。

< P>如果将反射添加到C++(使用第三方库或供应商扩展),则可以编写例程使用该反射数据来转储任意结构。例如,我有一些代码使用CERN的库对类或结构的成员进行迭代并将其转储到。

通常调试器非常聪明,可以这样做

在GDB中,您可以使用:

print structure
在NTSD中,您可以使用uber cool:

dt -r structure
如果您只是出于调试目的使用它,我强烈建议您学习使用调试器。即使它是您希望在您登录时记录的内容(即打印无数次),您也可以设置断点宏

在NTSD中:

bp yourdll!yourobject::yourfunction "dt -r structure;g"

我相信在GDB中也有一种方法可以做到这一点。事实上,在一个您可以使用GDB的环境中,您可以编译启用了调试符号的源代码(例如-ggdb),您可以使用调试器(例如,当您需要图形化的东西时,可以使用命令行中的GDB或ddd中的GDB)

考虑这段代码:

#include <string>
#include <vector>

struct test
{
    int a;
    float b;
    std::string c;
};

int main()
{
    std::vector<int> v;

    test t;
    t.a=1;
    t.b=2.0;
    t.c="hello there";


    return 0;
}
#包括
#包括
结构测试
{
INTA;
浮球b;
std::字符串c;
};
int main()
{
std::向量v;
试验t;
t、 a=1;
t、 b=2.0;
t、 c=“你好”;
返回0;
}
当礼貌地询问gdb时,它可以给我以下输出:

(gdb) break 20 Breakpoint 1 at 0x8048622: file bla.cpp, line 20. (gdb) run Starting program: /home/edb/a.out Breakpoint 1, main () at bla.cpp:21 21 return 0; (gdb) print t $1 = {a = 1, b = 2, c = {static npos = 4294967295, _M_dataplus = {> = {> = {}, }, _M_p = 0x96b6014 "hello there"}}} (gdb) ping v Undefined command: "ping". Try "help". (gdb) print v $2 = { >> = { _M_impl = {> = {> = {}, }, _M_start = 0x0, _M_finish = 0x0, _M_end_of_storage = 0x0}}, } (gdb)突破20 断点1位于0x8048622:文件bla.cpp,第20行。 (gdb)运行 启动程序:/home/edb/a.out 断点1,bla.cpp处的main():21 21返回0; (gdb)打印t $1={a=1,b=2,c={static npos=4294967295, _M_dataplus={>={>={},},{M_p=0x96b6014“你好”}} (gdb)平v 未定义的命令:“ping”。试试“帮助”。 (gdb)打印v $2 = { >> = { _M_impl={>={>={},},_M_start=0x0,_M_finish=0x0, _M_end_of_storage=0x0},}
编辑:请注意,此数据可从调试器上下文获得,要在运行时生成这些转储,您需要预见您自己的转储/格式化功能,通常通过重载来完成。为什么不使用二进制文件? fstream具有二进制模式,您可以转储除结构、类、命名空间或STL列表(如向量、队列)之外的任何类型。 要将结构、类、命名空间(或STL列表)转储为二进制文件吗?创建一个函数,并转储文件中的每个变量!结束!那不会那么难。。。 但需要更多帮助吗?请参阅此代码段

#include <iostream>
#include <fstream>//ofstream,ifstream
using namespace std;
ifstream myBdumpin ("data.bin"/*filename*/, ios::in);//ifstream = input
ofstream myBdumpout ("data.bin"/*filename*/, ios::out);//ofstream = output
int main()
{
    char a[8]="Binary!"
    myBdumpout << a;
    char b[8];
    myBdumpin >> b;
    if(a == b)cout << "It worked!" << endl;
    else cout << "It failed..." << endl;
    return 0;
}
#包括
#包括//流,ifstream
使用名称空间std;
ifstream myBdumpin(“data.bin”/*filename*/,ios::in)//ifstream=输入
流myBdumpout(“data.bin”/*filename*/,ios::out)//流量=输出
int main()
{
字符a[8]=“二进制!”
myBdumpout>b;

如果(a==b)不能,那么提供运算符()的唯一问题就存在了,而在本例中可能没有。我更喜欢命名的DumpOn(ostream&os)函数。@Neil:我不同意这一点,但我明白你的意思。实现运算符>>()它总是比较难,所以我通常不麻烦,但拥有它总是很好的。另一个问题是,想要有一个格式化的输出方法并不少见(op@Neil:是的,你经常两者都想要。在这种情况下,我倾向于使用op(),但这完全是偏好的问题。