Проверка определенности значений в C ++

StackOverflow https://stackoverflow.com/questions/473236

  •  19-08-2019
  •  | 
  •  

Вопрос

Я работаю на C ++, и мне нужно знать, является ли скалярное значение (например, double) является "определенным" или нет.Мне также нужно иметь возможность "отменить" это, если это необходимо:

class Foo {
public:
    double get_bar();

private:
    double bar;
    void calculate_bar() {
        bar = something();
    }
};

double Foo::get_bar() {
    if ( undefined(bar) )
        calculate_bar();
    return bar;
}

Возможно ли это на C ++?

Спасибо

Это было полезно?

Решение

Как говорится в других ответах, в C ++ нет этой концепции.Однако вы можете легко обойти это.

Либо у вас может быть неопределенное значение, которым вы инициализируете bar в конструкторе, обычно -1.0 или что-то подобное.

Если вы знаете, что calculate_bar никогда не возвращает отрицательных значений, вы можете реализовать функцию undefined в качестве проверки на < 0.0.

Более общим решением является наличие bool, в котором указывается, определен ли bar, который вы инициализировали значением false в конструкторе, и когда вы впервые устанавливаете его, вы меняете его на true. повышение:: необязательно делает это элегантным шаблонным способом.

Вот как выглядел бы приведенный вами пример кода.

class Foo {
public:
    double get_bar();
    Foo() : barDefined(false) {}
private:
    double bar;
    bool barDefined;
    void calculate_bar() {
        bar = something();
    }
};

double Foo::get_bar() {
    if ( barDefined == false ) {
        calculate_bar();
        barDefined = true;
    }
    return bar;
}

Другие советы

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

Если вы имеете в виду во время выполнения, то такой вещи не существует.Если bar никогда не инициализируется, в нем будут все случайные биты, которые там окажутся, в зависимости от того, как выделен объект (некоторые распределители инициализируют новую память равным нулю).

Редактировать:программист должен обрабатывать состояние объекта в конструкторах и / или ручных методах инициализации, таких как init()

Почему бы не сохранить отдельный флаг, который инициализируется значением false, а затем устанавливается в true при вычислении bar .Затем его можно "отменить", снова установив флаг в false.

if(!isBarValid)
{
    calculateBar();
    isBarValid = true;
}
return bar;

C ++ не имеет "неопределенного" состояния для примитивных типов.Ближайшим доступным для float / double было бы NAN, но на самом деле это имеет другое значение.

Это невозможно в C / C ++, примитивам всегда будет присваиваться значение (в основном мусор, все, что было в этом месте в памяти до него, если явно не назначено при объявлении).I обычно имеет значение-заполнитель (т.е.0 для указателей), который обозначает неиспользуемый, однако они также должны быть явно назначены.Если ваш double может принимать любое значение, то я предлагаю вам поместить рядом с ним логическое значение, которому изначально присвоено значение false, и протестировать / установить это значение, когда вы захотите выполнить свои вычисления.

Вы должны сделать это, используя дополнительное логическое значение.

Чтобы реализовать использование дополнительного логического значения, вы могли бы попробовать логику, подобную следующему шаблону:

template<typename T>
struct Defined
{
 bool defined;
 T value;
 Defined() : defined(false) {}
 Defined(const T& value_) : defined(true), value(value_) {}
 ... and perhaps other operators here ...
 ... to make this behave even more like a T ...
};

Вы могли бы попробовать Сконструируйте идиому первого использования и написать get_bar() вот так:

double & get_bar()
{
    static double *bar = new double(something());
    return *bar;
}

Когда ты позвонишь get_bar() это сделает bar для вас, если об этом еще никто не просил.Любые последующие вызовы будут просто возвращаться bar.Как говорится на связанной странице, технически это не приводит к утечке памяти, потому что ОС восстановит ее при завершении программы.

Обновить:

Изменил возвращаемое значение на double & чтобы позволить вам изменять bar.

Инициализировать bar к некоторому значению, которое никогда не может возникнуть, когда вы вызываете something() функция в конструкторе.

Например:

Foo(): bar(-1)
{
}

Затем проверьте значение -1 в get_bar функция.

(хммм, Ласераллан также опубликовал этот ответ за 1 минуту до этого :-( ;-) )

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top