初始化正在影响与初始化无关的代码

Posted

技术标签:

【中文标题】初始化正在影响与初始化无关的代码【英文标题】: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';
    

【问题讨论】:

Your code doesn't even compile 在输入帖子时出错。对不起。我已经对其进行了编辑以反映正确的代码。 Still doesn't compile double line[] = 1, 3, 2, 1; 在该范围内声明了一个新变量,该变量不以任何方式连接到具有相同名称的另一个变量,然后该范围结束,该变量也是如此。您的第一个循环所做的只是造成内存泄漏。 你的第一个 line 在每次迭代后都会被销毁,因此 v[x] 是一个悬空指针,会产生未定义的行为 【参考方案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[] 并直接使用大括号初始化器。

以上是关于初始化正在影响与初始化无关的代码的主要内容,如果未能解决你的问题,请参考以下文章

在MERN堆栈中工作时初始化Reducer时出错

java中的静态变量,静态方法与静态代码块详解

C++:当我添加看似无关的代码行时,分段错误消失了

对于从 IB 加载的 UItableViewController,非视图相关的初始化代码放在哪里

2.27专项测试补题

方便初始化与自我初始化