11 September 2009

С++0x и решение проблем инициализации

C++
C++0xВ статьях на хабре уже касались стандарта С++0x, а в частности лямбда-выражений. Я хотел написать еще про пару изменений и дополнений, которые внесут в С++. И без лишних слов сразу к делу.


Инициализация целочисленных переменных


С++0x решает проблему приведения элементраных вешественных типов к целочисленным. На простейшем примере это выглядит так:

Классический С++:

int a = 7.3; //Приведение к int все равно сработает
void func(int);
func(5.6); //И снова сработало приведение типов без нашего разрешения



В С++0x проблема решается с помощью введения новой конструкции для {}:

int x1 = {7.3}; //Ошибка приведения типов - и ошибка компиляции
double d = 7;
int x2 {d}; //И снова нельзя, произойдет ошибка
char x3{7}; //Все нормально
vector<int> vi = { 1, 2.3, 4, 5.6 }; //Не получится, так как нет соответствия



Делегирование конструкторов


В С++ необходимо иметь два конструктора для выполнения практически одинаковых действий или использовать дополнительную функцию.

Классический С++:

class X
{
int a;
validate(int x)
{
if (0<x && x<=max) a=x;
else throw bad_X(x);
}

public:
X(int x) //Конструктор с входным параметром типа int
{
validate(x);
}

X() //Конструктор по-умолчанию
{
validate(42);
}

X(string s) //Конструктор с входным параметром типа string
{
int x = lexical_cast<int>(s);
validate(x);
}
// ...
};



В С++0x один конструктор можно объявить в контексте другого конструктора:

class X
{
int a;

public:

X(int x) //Конструктор с входным параметром типа int
{
if (0<x && x<=max) a=x;
else throw bad_X(x);
}

X() :X{42} { } //Конструктор по-умолчанию

X(string s) :X{lexical_cast<int>(s)} { } //Конструктор с входным параметром типа string

// ...
}



Нулевые указатели



В стандартном С++ нулевой указатель представляет из себя обычный 0. В библиотеках можно встретить #define NULL 0. В С++0x вводится специальный литерал nullptr.

Пример использования:

char* p = nullptr;
int* q = nullptr;
char* p2 = 0; //Можно и по-старинке

void f(int); //Функция с входным параметром int
void f(char*); //Функция с входным параметром char*

f(0); //вызов f(int) - все нормально
f(nullptr); //вызов f(char*) - все нормально

void g(int);
g(nullptr); //Облом: nullptr не является int
int i = nullptr; //И снова облом



Заключиние


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

Продолжение следует…

Progg it
Tags:C++C++0x
Hubs: C++
+32
2.5k 27
Comments 38
Top of the last 24 hours