Определить инициализированные переменные - PullRequest
0 голосов
/ 01 декабря 2018

Есть ли способ проверить, инициализируется ли определенная переменная перед какой-то точкой в ​​программе?

Например, как проверить, инициализируется ли определенная переменная где-то перед узлом IfStmt?Методы класса VarDecl (hasInit() и getInit()) недостаточны из-за следующей ситуации:

int x = 0; // hasInit() return true

int y;
...
y = 0; // initialized here, but hasInit() returns false
...
if (...) {}

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

Во-первых, как упоминалось в комментариях:

int y = 0; // initialization
int y; y = 0; // assignment

Предположим, вы хотите обнаружить назначение.Одним простым способом может быть обтекание целого числа, которое вы хотите отслеживать в структуре, и запись пользовательского operator = (int).Например:

struct Foo 
{
   Foo() {std::cout << "default init" << std::endl;} 
   Foo& operator = (int elem) 
   { 
      cout<<"Int-Assignment operator called "<<endl;
      x = elem;
      is_assigned = true;
      return *this;
   }
   int x = 0; // default initialized to 0
   bool is_assigned = false; // default initialized to false
}; 

Теперь посмотрим, что произойдет:

int main() 
{ 
  Foo t1; 
  // t1.is_assigned is false
  t1 = 0; 
  // t1.is_assigned is true
  return 0; 
} 

Вы можете использовать что-то подобное или вариант, если это необходимо.Вот код , запущенный онлайн , соответствующий приведенному выше.

Это то, что вы хотели?

0 голосов
/ 01 декабря 2018

Если вы поддерживаете продукт, написанный на коде C ++, и надеетесь удалить уродливые неопределенные переменные, разумным способом сделать это будет определение инициализирующей функции или лямбда f, а затем объявление локальной переменной как const auto x = f(...); из get-go.

OTOH, если вы задерживаете присвоение значения с целью , существует несколько способов определить, назначено ли значение или нет.Я только что предложил следующие методы:


std :: необязательный

В C ++ 17 и более, std::optional<T> позволяет нам определять, являются ли значенияназначены или нет.std::optional::has_value и std::optional::value соответствуют вашим hasInit и getInit соответственно следующим образом:

DEMO

#include <iostream>
#include <optional>

template<typename T>
void checkInitialization(const std::optional<T>& a)
{
    if(a.has_value()){            
        std::cout << "Value is assigned by " << a.value() << "." << std::endl;
    }
    else{
        std::cout << "Value is still not assigned." << std::endl;
    }
}

int main(void)
{
    std::optional<int> x;

    checkInitialization(x); // Value is still not assigned

    x = 1;
    checkInitialization(x); // Value is assigned

    return 0;
}

Theвывод выглядит следующим образом:

Значение по-прежнему не назначено.

Значение присваивается 1.


std ::unique_ptr

Мы также можем проверить это, используя std::unique_ptr<T>, который представлен в C ++ 11.Сначала мы определяем переменную как std::unique_ptr<T> x;, где (x == nullptr) все еще имеет значение true.Позже мы присваиваем значение x = std::unique_ptr<int>(new int(1)), а затем (x == nullptr) становится ложным.(В C ++ 14 x = std::make_unique<int>(1) работает и прост.) Таким образом, мы снова можем получить предыдущий вывод со следующим кодом:

DEMO

#include <iostream>
#include <memory>

template<typename T>
bool hasInit(const std::unique_ptr<T>& a)
{
    return (a != nullptr);
}

template<typename T>
const T& getInit(const std::unique_ptr<T>& a)
{
    return *a;
}

template<typename T>
void checkInitialization(const std::unique_ptr<T>& a)
{
    if(hasInit(a)){   
        std::cout << "Value is assigned by " << getInit(a) << "." << std::endl;
    }
    else{
        std::cout << "Value is still not assigned." << std::endl;
    }
}

int main(void)
{
    std::unique_ptr<int> x;

    checkInitialization(x); // Uninitialized

    x = std::unique_ptr<int>(new int(1));
    //x = std::make_unique<int>(1); // C++14
    checkInitialization(x); // Initialized

    return 0;
}

std :: pair

Мы также можем применить std::pair<bool, T>, где std::pair::first и std::pair::second соответствуют вашим hasInit и getInitсоответственно.Мы снова получаем предыдущий вывод:

DEMO

#include <iostream>
#include <utility>

template<typename T>
void checkInitialization(const std::pair<bool, T>& a)
{
    if(a.first){   
        std::cout << "Value is assigned by " << a.second << "." << std::endl;
    }
    else{
        std::cout << "Value is still not assigned." << std::endl;
    }
}

int main(void)
{
    std::pair<bool, int> x{false, 0};

    checkInitialization(x); // Uninitialized

    x = {true, 1};
    checkInitialization(x); // Initialized

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...