Обсуждение:C++11

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Мнится мне, что на английском эта статья будет понятнее, ибо русский текст просто набор бессмысленных предложений. Придётся читать английскую версию:(

Неясности[править код]

конструктор переноса std::vector::vector(vector &&x) может просто перенести указатель и длину в новый объект, опустошив x[ЩИТО?].

Что это значит? Будет ли вызван деструктор, если конструктор вызывается при приведении типов? Что значит "просто перенести"? С какимим целями введён в стандарт constexpr? Не для чего, а почему? Особенно интересно зачем для функций.

Тривиальный класс — это класс, который: содержит тривиальный конструктор по умолчанию,

Гениально. X is so X.
А что такое "тривиальный конструктор" и прочие "тривиальности"?

Во-первых, определение явно инициализируемой переменной может содержать ключевое слово auto.

1. Пожалуй, стоит указать, что ключевое слово auto существовало в прошлом стандарте, но здесь его значение изменено.
2. Не совсем понятно, как программисту работать с типом, которого он не знает, в случае с контейнером в примере (auto someStrangeCallableType = std::bind(&SomeFunction, _2, _1, someObject);).

for(int &x : my_array)
Похоже, следующий стандарт будет Perl. 109.161.90.147 16:50, 31 августа 2013 (UTC)[ответить]

/Неясности[править код]

В тексте статьи использована фраза - "Например, std::vector — это простая обёртка вокруг Си-массива и переменной, хранящей его размер."

Позволю себе не согласиться. Стандарт С++ никоим образом не описывает внутреннее представление std::vector. Он лишь описывает интерфейс взаимодействия.

В частности современные реализации vector'a довольно сложны, и могут содержать внутри себя списки блоков данных (linked lists). О простоте тут речи быть не может.

178.121.121.16 00:06, 11 августа 2012 (UTC)[ответить]
Вообще-то, стандарт гарантирует, что элементы вектора располагаются последовательно в одном болке памяти. 77.247.211.6 11:10, 9 января 2014 (UTC)[ответить]

Плохие примеры[править код]

В статье используются примеры, содержащие типичные ошибки программирования. Например, переписанная функция printf():

void printf(const char *s)
{
    while (*s) {
        if (*s == '%' && *(++s) != '%')
            throw std::runtime_error("invalid format string: missing arguments");
        std::cout << *s++;
    }
}

template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
    while (*s) {
        if (*s == '%' && *(++s) != '%') {
            std::cout << value;
            ++s;
            printf(s, args...); // продолжаем обработку аргументов, даже если *s == 0
            return;
        }
        std::cout << *s++;
    }
    throw std::logic_error("extra arguments provided to printf");
}

может повести себя неопределëнным образом при вызове printf("%", "str1", "str2").178.130.5.13 22:07, 10 апреля 2012 (UTC)[ответить]

ВП:Правьте смело. Приведите свои примеры, которые на ваш взгляд лучше для данной статьи. Все будут только рады. --Dnikitin 05:51, 11 апреля 2012 (UTC)[ответить]
К сожалению, я почти не знаю C++11, поэтому и читал эту статью.178.130.5.13 12:50, 18 апреля 2012 (UTC)[ответить]


Также иногда используются имена переменных, более характерных для java-coding-style, чем для c-style. Например, имя переменной moonGravity более характерно для java, для c более употребимо moon_gravity 176.109.125.244 09:44, 27 мая 2012 (UTC)[ответить]

Добавить в раздел "Константа нулевого указателя"[править код]

Следует добавить ещё один пример вредосности NULL в С++.

Иногда программисту С++ приходится писать функции с переменным числом параметров.

Рассмотрим пример добавления дочерних виджетов для какого-то "окна":

// принимает список дочерних элементов текущего окна. конец списка - NULL

void Widget::AddChildWidgets(...);

Widget myWindow;

Button btn1, btn2;

Scrollbar scroll1;

myWindow.AddChildWidgets(&btn1, &btn2, &scroll1, NULL);

Данный код абсолютно корректен для платформы i386. Дело в том что sizeof(Widget*)=4. А ещё sizeof(NULL)=sizeof(int)=4 , так как NULL=0.

Но это совершенно не работает для платформы AMD64. Дело в том что sizeof(Widget*)=8. А ещё sizeof(NULL)=sizeof(int)=4 , так как NULL=0.

В последнем случае на стек ляжет только 4 байта вместо положенных 8. Функция AddChildWidgets благополучно извлечёт со стека 8 байт. Разумеется из них только 4 байта будут равны нулю, то есть как минимум функция ошибётся с количеством ей переданных параметров, и будет продолжать читать машинный стек пока не нарвётся на 8 подряд идущих нулевых байт либо пока не сработает аппаратная защита. Ну и конечно же все полученные указатели, начиная с 4-го будут некорректными и попытка сделать что-либо с ними полезное (вызов функции или чтение/модификация данных) вызовет ошибку доступа к памяти.

Одно из требований, предъявляемых к указателю nullptr (в стандарте это оговорено, но в данной статье не написано) это гарантия справедливости выражения:

sizeof(nullptr)=sizeof(void*)=sizeof(указатель любого типа).

Таким образом заменив выше приведённый пример на myWindow.AddChildWidgets(&btn1, &btn2, &scroll1, nullptr);

мы добъёмся его полной работоспособности на любой платформе.

Следует также отметить что nullptr может быть реализован программно в виде подключаемого заголовочного файла (для тех компиляторов и/или их версий, которые пока что не поддерживают nullptr на уровне языка). В интернете можно найти несколько подобных реализаций. Однако следует быть внимательным - для многих таких доморощенных реализаций не соблюдается правило размерности указателя и nullptr. 178.121.121.16 23:42, 10 августа 2012 (UTC)[ответить]