考虑以下示例:
#include <iostream>
#include <sstream>
#include <vector>
#include <wchar.h>
#include <stdlib.h>
using namespace std;
struct odp {
int f;
wchar_t* pstr;
};
int main()
{
vector<odp> vec;
ostringstream ss;
wchar_t base[5];
wcscpy_s(base, L"1234");
for (int i = 0; i < 4; i++)
{
odp foo;
foo.f = i;
wchar_t loopStr[1];
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
foo.pstr[0] = base[i];
vec.push_back(foo);
}
for (vector<odp>::iterator iter = vec.begin(); iter != vec.end(); iter++)
{
cout << "Vec contains: " << iter->f << ", " << *(iter->pstr) << endl;
}
}
这将产生:
Vec contains: 0, 52
Vec contains: 1, 52
Vec contains: 2, 52
Vec contains: 3, 52
我希望每次
iter->f
和iter->pstr
都会产生不同的结果。不幸的是,iter->pstr
始终相同。我怀疑每次循环时都会创建一个新的
loopStr
。而不是将其复制到结构中,而是仅复制一个指针。指针写入的位置将被覆盖。如何避免这种情况?是否可以解决此问题而无需在堆上分配内存?
最佳答案
...
odp foo;
foo.f = i;
wchar_t loopStr[1]; //A
foo.pstr = loopStr; //B
foo.pstr[0] = base[i]; //C
vec.push_back(foo);
...
A-您将一个数组(大小为1)分配给堆栈
B-您指定foo.pstr指向堆栈上的数组
C-您将base [i]分配给数组的第一个元素(在堆栈上)
在for循环退出其当前循环之后,变量loopStr不在范围内,并且其内容未定义。下一次循环迭代将使大多数likley重用相同的内存地址(因此,为什么在最后打印时会得到相同的值)。如果您启用了优化功能,则C编译器可能会警告您获取局部变量的地址(尽管我对此表示怀疑)。
在不使用任何堆分配的情况下,我认为您唯一的选择是在odp中固定foo.pstr的大小,即
struct odp {
int f;
wchar_t pstr[1];
};
或作为odp初始化的一部分在堆上分配数组
...
odp foo;
foo.f = i;
foo.pstr = new wchar_t [1];
foo.pstr[0] = base[i];
vec.push_back(foo);
...
最好还是使用std :: wstring,因为您正在使用c ++,并让它为您执行内存分配和管理。
关于c++ - C++:指针,循环变量和结构麻烦,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3058006/