Инициализация влияет на код, который не связан с инициализацией - PullRequest
0 голосов
/ 01 сентября 2018

В следующем коде я думал, что последний цикл будет печатать 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';
    }
}

1 Ответ

0 голосов
/ 01 сентября 2018

Здесь

 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 });

даст вектор массивов (2-х мерный) с размером 4x4. И получить к ним доступ, используя цикл на основе диапазона:

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

Тем не менее, похоже, что вы делаете задание, где вы должны иметь дело с std::vector <int*> 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

Однако я бы предложил использовать умных указателей , поскольку вы склоняетесь к 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...