【问题标题】:An initialization is affecting code that has no connection to the initialization初始化正在影响与初始化无关的代码
【发布时间】:2018-09-01 07:00:07
【问题描述】:

在下面的代码中,我认为最后一个循环会打印四次1 2 3 4,每换行一次。代码打印了四次 1 3 2 1 而不是 1 2 3 4

  • 如果我将{1, 3, 2, 1} 的类型从double 更改为int,问题就会消失。
  • 如果我将double line[] = {1, 3, 2, 1} 从 if-else 块中取出,问题就会消失。

我只是无法理解变量double line[] 的初始化如何影响vector <double *> v 的赋值。

#include <iostream>
#include <cmath>
#include <vector>

int main()
{
    std::vector <double*> v;
    for(int i = 0; i < 4; i++)
    {
        double line[] = {1, 2, 3, 4};
        v.push_back(new double[4]);
        v[std::abs(v.size()) - 1] = line;
    }
    if(0 > 1)
    {

    }
    else
    {
        double line[] = {1, 3, 2, 1};
    }
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            std::cout << v[i][j] << ' ';
        }
        std::cout << '\n';
    }
}

【问题讨论】:

  • 在输入帖子时出错。对不起。我已经对其进行了编辑以反映正确的代码。
  • double line[] = {1, 3, 2, 1}; 在该范围内声明了一个新变量,该变量不以任何方式连接到具有相同名称的另一个变量,然后该范围结束,该变量也是如此。您的第一个循环所做的只是造成内存泄漏。
  • 你的第一个 line 在每次迭代后都会被销毁,因此 v[x] 是一个悬空指针,会产生未定义的行为

标签: c++ c++11 pointers


【解决方案1】:

这里

 for(int i = 0; i < 4; i++)
    {
        double line[] = {1, 2, 3, 4};      
        v.push_back(new double[4]);
        v[std::abs(v.size()) - 1] = line;
    }

您所拥有的只是内存泄漏 + 未定义的行为。

您正在堆栈中创建line,作为每个迭代器的结尾,它超出了范围,这意味着您没有按照您的意图进行操作。访问后,它们会为您提供 UB。 其次,您每次都在堆中创建new double[4],而您没有管理/释放后者,导致内存泄漏!

你可能想这样做:

#include <vector>
#include <array>

std::vector <std::array<int, 4>> v;

for (int i = 0; i < 4; i++) v.emplace_back(std::array<int, 4>{ 1, 2, 3, 4 });

将给出一个 4x4 维度的数组向量(二维)。 并使用基于范围的循环访问它们:

for (const std::array<int, 4>& row : v)
{
    for (const int element : row) std::cout << element << " ";
    std::cout << std::endl;
}

但是,您似乎正在执行任务,您必须以std::vector &lt;int*&gt; v; 方式处理。如果是这样,则需要进行额外的取消分配以释放您使用 new 关键字创建的内存。

std::vector <int*> v;

for (int i = 0; i < 4; i++) 
    v.emplace_back(new int[4]{ 1, 2, 3, 4 }); // create and store to vector

for (const int* row : v)
    for (int j = 0; j < 4; j++)
    // do print

for (int i = 0; i < 4; i++)  delete[] v[i];   // free the memory using delete

但是,我建议使用 smart pointers,因为您倾向于 C++ 而不是 C。 比如上面的代码可以写成std::unique_ptr

std::vector <std::unique_ptr<int[]>> v;

for (int i = 0; i < 4; i++)
    v.emplace_back(std::unique_ptr<int[]>(new int[4]{ 1, 2, 3, 4 }));

for (const std::unique_ptr<int[]>& row : v)
    for (int j = 0; j < 4; j++)
        std::cout << row[j] << " ";
 // no mannual memory management is required.

【讨论】:

  • std::vector&lt;std::array&lt;double,4&gt;&gt; 是更好的选择。
  • @PaulMcKenzie 你是对的,因为大小是固定的。让我更新一下。
  • 另外,通过使用std::array,OP 的代码几乎不需要更改。所需要做的就是从代码中完全删除 line[] 并直接使用大括号初始化器。
猜你喜欢
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多