在cpp函数中初始化多个结构
Initializing multiple structs in cpp function
我想在循环中初始化结构并更新到数组。以下是我正在使用的代码。
#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
您正在将指向局部变量的指针存储在您删除它们后访问的对象中。
即使 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";
}
}
这里最大的问题是这是 C 而不是 C++,但是,让我们考虑一个 C 解决方案:
有几个问题:
struct Response {
Record *records[];
};
不要忘记为数组指定维度:
Record *records[4];
下一个:
struct Record {
char *name;
};
这只是声明了一个名为name的指针,并没有分配给name指向的内存。以后需要给name分配内存,或者在这里做成静态数组,而不是指针。
record->name = (char*)x;
现在 name 指向一个静态数组 x。每次循环都会发生这种情况,因此所有 record->name 实例都将指向同一个数组。这就是为什么他们都打印相同的值:-)
你需要将x中的字符串复制到record->name,这个你做不到,因为没有record->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";
}
}
我想在循环中初始化结构并更新到数组。以下是我正在使用的代码。
#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
您正在将指向局部变量的指针存储在您删除它们后访问的对象中。
即使 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";
}
}
这里最大的问题是这是 C 而不是 C++,但是,让我们考虑一个 C 解决方案:
有几个问题:
struct Response {
Record *records[];
};
不要忘记为数组指定维度:
Record *records[4];
下一个:
struct Record {
char *name;
};
这只是声明了一个名为name的指针,并没有分配给name指向的内存。以后需要给name分配内存,或者在这里做成静态数组,而不是指针。
record->name = (char*)x;
现在 name 指向一个静态数组 x。每次循环都会发生这种情况,因此所有 record->name 实例都将指向同一个数组。这就是为什么他们都打印相同的值:-) 你需要将x中的字符串复制到record->name,这个你做不到,因为没有record->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";
}
}