Динамический массив bool в C

#c #arrays #dynamic #boolean

#c #массивы #динамический #логическое значение

Вопрос:

 // All right? This is really good working code? 
//Need init array with value "false"

bool **Madj;
int NodeCount=4;

bool **Madj = new bool*[NodeCount];
for (int i=0; i<NodeCount; i  ){
    Madj[i] = new bool [NodeCount];
    for (int j=0; j<NodeCount; j  ){
        Madj[i][j] = false;
    }
}
  

Комментарии:

1. Вы его тестировали? В чем ошибка и в чем ваш вопрос?

2. Да, это создаст матрицу логических значений размером 4×4. Нет, это не особенно хорошо; Madj объявляется дважды без необходимости, и код подвержен утечкам памяти.

3. @Emile: это так, но я не настолько уверен, что ему здесь не место, чтобы голосовать за закрытие. Code Review все еще находится в бета-версии, поэтому мы не можем направлять вопросы туда.

Ответ №1:

Вы могли бы рассмотреть возможность использования встроенного многомерного массива Boost в качестве менее хрупкой альтернативы. Как уже отмечалось, предоставленный вами код будет работать, но имеет проблемы.

Ответ №2:

Как насчет:

 std::vector<std::vector<bool> >   Madj(4,std:vector<bool>(4, false));
  

К сожалению, std::vector<bool> специализируется на оптимизации размера (не скорости).
Поэтому он может быть неэффективным (особенно при частом использовании). Таким образом, вы могли бы использовать массив int (если вы обнаружите, что версия bool замедляет вашу работу).

 std::vector<std::vector<int> >   Madj(4,std:vector<int>(4, 0));
  

Примечание: значение int может использоваться в логическом контексте и автоматически преобразовываться (0 => false, любое другое число равно true (хотя лучше всего использовать 1).

Ответ №3:

По крайней мере, IMO, если вы настаиваете на том, чтобы делать это вообще, обычно вы должны делать это по-другому, что-то вроде:

 class bool_array { 
     bool *data_;
     size_t width_;

     // no assignment or copying
     bool_array amp;operator=();
     bool_array(bool_array const amp;);
public:
     bool_array(size_t x, size_t y) width_(x) {
         data_ = new bool[x*y];
         std::fill_n(data_, x*y, false);
     }

     bool amp;operator()(size_t x, size_t y) { 
         return data_[y width_ x];
     }

     ~bool_array() { delete [] data_; }
};
  

Это можно приукрасить (например, используя прокси для обеспечения постоянства), но общая идея остается: 1) выделите ваши bool файлы в одном блоке, и 2) поместите их в класс, и 3) перегрузите оператор для поддержки достаточно чистой индексации данных.

Вам также следует рассмотреть возможность использования std::vector<bool> . В отличие от других экземпляров std::vector , это не контейнер (как стандарт определяет этот термин), что может сбить с толку — но то, что вы создаете, также не является контейнером, так что это, по-видимому, не имеет значения для вас.

Комментарии:

1. В чем потенциальная опасность его заполнения с помощью цикла for в случае утечки памяти? Не могли бы вы указать мне на какую-нибудь статью об этом в Интернете?

2. @Hossein: Я не совсем уверен, о чем вы спрашиваете. Часть идеи инкапсуляции его в объект заключается в том, чтобы гарантировать, что память не протекает.

Ответ №4:

 bool **Madj = new bool*[NodeCount];
for (int i=0; i<NodeCount; i  ){
    Madj[i] = new bool [NodeCount];
    for (int j=0; j<NodeCount; j  ){
        Madj[i][j] = false;
    }
}
  

Если первый вызов new завершается успешно, но какой-либо из вызовов в цикле завершается неудачей, то с тех пор произошла утечка памяти, Madj и подмассивы вплоть до текущего i не удаляются. Используйте vector<vector<bool> > или vector<bool> размера NodeCount * NodeCount . Используя последний вариант, вы можете перейти к элементу ( i , j ) с помощью [i*NodeCount j] .

Ответ №5:

Я думаю, что это выглядит прекрасно!

В зависимости от использования, вы могли бы использовать std::vector вместо необработанного массива.

Но верно, что первое объявление Madj должно быть «extern», чтобы избежать ошибок связывания или затенения.

Комментарии:

1. Это правда, но они являются только потенциальными. Если у вас на столе стоит ваза, она может разбиться, упав на пол.

2. (ссылаясь на утечки памяти, на которые я указал; с тех пор я удалил комментарий): вы защищаете небрежное программирование, которое в современном мире может стоить больших денег или жизней.

3. @larsmans Неаккуратная часть — это когда вы забываете перераспределить память. Полагаясь на автоматические гарантии, вы только перемещаете проблему в другое место. Утечки памяти и сбои — это лишь малая часть всех существующих ошибок, и у вас нет автоматических гарантий для неправильно реализованной логики. Я полностью поддерживаю код OP. Я понимаю, что это создает «риск» ошибки освобождения памяти, но каждая строка кода является потенциальным источником ошибок.

4. Код операционной системы не является потенциальным источником ошибок, он содержит баги.

5. @larsmans Содержит ли он какую-либо другую ошибку, кроме повторяющегося объявления Madj, которое было бы обнаружено цепочкой инструментов компилятор-компоновщик?

Ответ №6:

Если у вас есть только bool s, рассмотрите возможность использования bitset s. Вы можете объединить это с другими контейнерами для многомерных массивов, например vector<bitset> .