我想在循环中初始化结构并更新到数组。我正在使用以下代码。
#include <iostream>
struct Record {
char *name;
};
struct Response {
Record *records[];
};
int main()
{
Response *response = new Response;
for(int i=0; i<4; i++) {
Record *record= new Record();
char x[20];sprintf(x, "%d", i);
record->name = (char*)x;
response->records[i] = record;
std::cout << "Inserting: " << x << "\n";
//Not sure if I have to delete.
delete record;
}
for(int i=0; i<4; i++) {
std::cout << "Fetching: " << response->records[i]->name << "\n";
}
}
奇怪的是,打印数组中的所有项目都打印相同的值。关于什么可能出错的任何想法,评论或想法?
示例输出:
Inserting: 0
Inserting: 1
Inserting: 2
Inserting: 3
Fetching: 3
Fetching: 3
Fetching:
Fetching: 3
答案 0 :(得分:5)
您将指向删除它们后访问的对象中的局部变量的指针存储起来。
即使Response::records
的大小合适,这两个因素也会导致代码无效。
惯用C ++会使用std::string
和std::vector<Record>
,但如果你真的想要C风格的字符串和数组,这应该可行:
struct Record {
char name[20];
};
struct Response {
Record records[4];
};
int main()
{
Response response;
for(int i = 0; i < 4; i++) {
Record record;
sprintf(record.name, "%d", i);
response.records[i] = record;
std::cout << "Inserting: " << record.name << "\n";
}
for(int i = 0; i < 4; i++) {
std::cout << "Fetching: " << response.records[i].name << "\n";
}
}
答案 1 :(得分:3)
这里最大的问题是C不是C ++,但是,让我们考虑一个C解决方案:
有一些问题:
struct Response {
Record *records[];
};
别忘了为你的阵列提供尺寸:
Record *records[4];
下一步:
struct Record {
char *name;
};
这只是声明一个名为name的指针,没有为name指定的内存。您将来需要为name分配内存,或者在此处将其设置为静态数组而不是指针。
record->name = (char*)x;
现在name指向静态数组x。每次循环都会发生这种情况,因此所有记录 - &gt;名称实例都将指向同一个数组。这就是他们为什么都打印相同价值的原因:-) 您需要将x中的字符串复制到record-&gt; name,这是您无法做到的,因为没有与record-&gt; name关联的存储空间。
两种出路是:
struct Record {
char name[20]; // static array
};
...
char x[20] = {0}; // initialise so we're sure of a terminating null
strcpy(record->name, x);
或者
struct Record {
char *name;
};
...
record->name = new char[20];
strcpy(record->name, x);
最后,
//Not sure if I have to delete.
delete record;
不,你不能在这里删除,因为这些记录将在之后使用。如果你必须删除,设置类似你的初始化循环,但在main()结束之前,只有这一次你将被破坏。 当然,严格地说,因为这是C,你不应该使用new和delete。 malloc()和free()系列调用更适合C风格。 new和delete相对于malloc()和free()的主要优点是在适当的时候调用已分配对象的构造函数和析构函数,但是您还没有使用这些函数中的任何一个。
这在C ++中会更容易,更简单,更安全。你必须用C语言做,还是考虑C ++?
#include <iostream>
#include <cstring>
struct Record {
char *name;
};
struct Response {
Record *records[4];
};
int main()
{
Response *response = new Response;
for(int i=0; i<4; i++) {
Record *record= new Record();
char x[20];sprintf(x, "%d", i);
record->name = new char[20];
strcpy(record->name, x);
response->records[i] = record;
std::cout << "Inserting: " << x << "\n";
//Not sure if I have to delete.
//delete record;
}
for(int i=0; i<4; i++) {
std::cout << "Fetching: " << response->records[i]->name << "\n";
}
// the program is about to exit and the resources will be freed by the system, so this is not strictly necessary
for(int i=0; i<4; i++) {
delete [] response->records[i]->name;
delete response->records[i];
}
delete response;
}
编辑:这是一个可能的解决方案,它更加C ++友好,没有原始指针,所有内存分配都由字符串和向量中的标准库处理。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Record {
Record(string record_name) : name (record_name) {}
string name;
};
struct Response {
vector<Record> records;
};
int main()
{
Response response;
for(int i=0; i<4; i++) {
response.records.push_back(Record(to_string(i)));
std::cout << "Inserting: " << i << "\n";
}
for (auto r : response.records) {
cout << "Fetching: " << r.name << "\n";
}
}