0

有人可以解释为什么下一个代码输出 26 timez 'Z' 而不是从 'A' 到 'Z',以及如何正确输出这个数组。看代码:

wchar_t *allDrvs[26];
    int count = 0;
     for (int n=0; n<26; n++)
     {
         wchar_t t[] = {L'A' + n, '\0'}; 
         allDrvs[n] = t;
         count++;
     }
     int j;
     for(j = 0; j < count; j++)
     {
        std::wcout << allDrvs[j] << std::endl;
     }
4

3 回答 3

5

问题(至少一个)是:

{
     wchar_t t[] = {L'A' + n, '\0'}; 
     allDrvs[n] = t;  //allDrvs points to t
     count++;         
 }   //t is deallocated here
     //allDrvs[n] is a dangling pointer

所以,简短的回答 - 未定义的行为就行了std::wcout << allDrvs[j]

要获得正确的输出 - 有一个蹩脚的丑陋的版本涉及动态分配和数组之间的复制。

然后是使用std::vector<std::wstring> >.

于 2012-10-23T14:24:41.437 回答
0

t[]在堆栈上;它一次只存在于循环的一次迭代中,下一次迭代似乎正在重用该空间 - 这不是必需的行为,但这似乎是根据您的结果发生的情况。如果allDrvs[]在第一个循环完成后使用调试器进行检查,您可能会看到所有指针都指向同一个内存位置。

有多种方法可以解决这个问题。您可以为每次循环迭代在堆上分配一个新t的(然后删除它们)。您可以wchar_t allDrvs[26][2];代替, 并在每次迭代wchar_t *allDrvs[26]中复制 的内容。t您可以t在第一个循环中立即显示,而不是稍后再显示。您可以使用std::vectorstd::wstring为您管理事物,而不是使用数组和指针。

于 2012-10-23T14:28:42.887 回答
0

您的代码具有未定义的行为。你t有自动存储持续时间,所以一旦你退出上层循环,它就不复存在了。您allDrvs包含 26 个指向在您在第二个循环中使用它们时已销毁的对象的指针。

t碰巧的是,它看起来像(在您运行它的情况下,使用您正在使用的编译器等)正在发生的事情是它在循环的每次迭代中重新使用相同的存储空间,以及何时您allDrvs在第二个循环中使用,该存储尚未被覆盖,因此您有 26 个指向相同数据的指针。

既然您无论如何都在使用 C++,我建议您使用std::wstring并且可能std::vector代替 - 例如,按照这个一般顺序:

std::vector<std::wstring> allDrvs;

for (char i=L'A'; i<L'Z'; i++)
     allDrvs.push_back(std::wstring(i));

从技术上讲,这不是完全可移植的——它依赖于'A' .. 'Z'连续性,并非所有字符集都是如此,IBM 的 EBCDIC 是明显的例外。即使在这种情况下,它也会产生所有正确的输出,但它还会包含一些您并不真正想要的附加项目。

尽管如此,原始代码依赖于'A'..'Z'连续性,而且代码看起来可能是针对 Windows 的,所以这可能不是一个大问题。

于 2012-10-23T14:29:37.810 回答