“foreach оценивает” макрос в gcc и cpp

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
12
задан xian 17 June 2009 в 03:24
поделиться

7 ответов

Можно сделать это использование двух циклов. Первое объявляет итератор с именем, которое является функцией контейнерной переменной (и можно сделать это более ужасным, если Вы волнуетесь по поводу конфликтов со своим собственным кодом). Второе объявляет переменную значения.

#define ci(container) container ## iter
#define foreach_value(var, container) \
    for (typeof((container).begin()) ci(container) = container.begin(); \
         ci(container) != container.end(); ) \
        for (typeof(ci(container)->second)* var = &ci(container)->second; \
             ci(container) != container.end(); \
             (++ci(container) != container.end()) ? \
                 (var = &ci(container)->second) : var)

При помощи того же условия выхода из цикла внешний цикл только происходит однажды (и если Вы удачливы, оптимизирован далеко). Кроме того, Вы стараетесь не звонить-> второй на итераторе, если карта пуста. Это - та же причина тернарного оператора в инкременте внутреннего цикла; в конце мы просто оставляем var в последнем значении, так как на это не сошлются снова.

Вы могли встроить ci (контейнер), но я думаю, что он делает макрос более читаемым.

4
ответ дан 2 December 2019 в 19:00
поделиться

Вы искали бы BOOST_FOREACH - они уже сделали всю работу для Вас!

Если Вы действительно хотите к самокрутке, можно объявить блок где угодно в C++, который решает вопрос объема с промежуточным устройством хранения данных itr-> второй...

// Valid C++ code (which does nothing useful)
{
  int a = 21; // Which could be storage of your value type
}
// a out of scope here
{ 
  int a = 32; // Does not conflict with a above
}
8
ответ дан 2 December 2019 в 19:00
поделиться

STL преобразовывает функцию, также делает что-то подобное.

Аргументы (в порядке):

  1. Входной итератор, определяющий начало контейнера
  2. Входной итератор, определяющий конец контейнера
  3. Выходное определение итератора, куда поместить вывод (для оперативного преобразования, подобного для - каждый, просто передача входной итератор в № 1)
  4. Унарная функция (функциональный объект) для выполнения на каждом элементе

Для очень простого примера Вы могли использовать для своей выгоды каждый символ в строке:

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

int main(int argc, char* argv[]) {
    std::string s("my lowercase string");
    std::transform(s.begin(), s.end(), s.begin(), toupper);
    std::cout << s << std::endl; // "MY LOWERCASE STRING"
}

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

3
ответ дан 2 December 2019 в 19:00
поделиться

Вы могли определить шаблонный класс, который берет тип mymap как шаблонный параметр и действует как итератор по значениям путем перегрузки * и->.

0
ответ дан 2 December 2019 в 19:00
поделиться

Вы думали о пользовании библиотеками Boost? У них есть a foreach макрос, реализованный, который, вероятно, более устойчив, чем что-нибудь, что Вы запишете... и, существует также transform_iterator который, казалось бы, смог бы использоваться, чтобы сделать часть второго извлечения того, что Вы хотите.

К сожалению, я не могу сказать Вам точно, как использовать его, потому что я не знаю достаточно C++ :) Этот поиск Google поднимает некоторые многообещающие ответы: comp.lang.c ++. модерируемый, Повышение transform_iterator вариант использования.

1
ответ дан 2 December 2019 в 19:00
поделиться

Повышение:: For_each является безусловно Вашим лучшим выбором. Изящная вещь состоит в том, что то, что они на самом деле дают Вам, является макро-BOOST_FOREACH (), который можно затем перенести и #define к тому, что действительно требуется назвать им в коде. Большинство все выберут старый добрый "foreach", но другие магазины могут иметь различные стандарты кодирования, таким образом, это соответствует тому мышлению. Повышение также имеет много других положительных героев для разработчиков C++! Определенно стоящий использования.

1
ответ дан 2 December 2019 в 19:00
поделиться
#define foreach(var, container) for (typeof((container).begin()) var = (container).begin(); var != (container).end(); ++var)

Нет никакого typeof в C++..., как это компилирует для Вас? (это, конечно, не портативно),

0
ответ дан 2 December 2019 в 19:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: