• Почему у временного объекта можно вызывать non-const метод?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    // Causes compile-time errors:
    //! f7(f5());

    Смотри, а ещё можно вот так сделать:
    class X {
     int i;
    public:
     X(int ii = 0);
     void modify();
     X& ref() {return *this;}
    };
    ...
    f7(f5().ref());
    Ответ написан
    1 комментарий
  • Почему у временного объекта можно вызывать non-const метод?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По поводу вызова неконстантных методов - а с чего вы взяли, что они не дожны быть возможны? Временные объекты не имеют const квалификаторов. Иначе нельзя было бы делать вещи типа SomethingBuilder().WithA().WithB().Finalize().

    //! f6() = X(1);

    Оператор присвоения требует Lvalue слева. Временный объект же - Rvalue. Eго можно ставить только справа от =. А не потому что у него const квалификатор.

    Это сделано скорее всего потому, что, ну, нет же смысла перезаписывать временный объект. Он временный, к нему потом никак не обратиться.

    //! f6().modify();

    Вот тут попытка вызова неконстантного метода у константного (и временного - но это не важно) объекта.

    //! f7(f5());

    Видимо, это чтобы исключить некоторый класс ошибок. Если вы передаете в качестве неконстантной ссылки что либо, значит оно должно внутри менятся и снаружи эти изменения должны быть видны. Иначе можно было бы передавать по константной ссылке или по значению. Но вы передаете туда временный объект - его никак снаружи видно не будет. Он существует только в этой строчке. Поэтому в C++ нельзя инициализировать неконстантные lvalue ссылки через rvalue (временные объекты).
    Ответ написан
    1 комментарий
  • Почему нельзя возвращать объект по значению в non-const &?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Первое - это Retrun Value Optimization. Компилятор видит, что результат работы функции используется для инициализации переменной и вместо выделения памяти под временный объект и копирования сразу заполняет результат.

    По поводу ссылки. Результат работы функции в вашем случае - prvalue

    там же по ссылке написано:
    An rvalue may be used to initialize a const lvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

    An rvalue may be used to initialize an rvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.


    Т.е. стандартом запрещено инициализировать не const ссылку через prvalue.

    Почему это сделано? Потому что эти самые prvalue/rvalue по сути являются временными объектами. У них нельзя взять адрес, у них нет имени, компилятор может засунуть их куда угодно и уничтожить сразу за текущим выражением.

    Если бы можно было делать ссылку на эти временные объекты и как-то их менять потом, это бы усложняло анализ и возможность некоторых оптимизаций. Как, например, RVO в вашем вопросе. Пришлось бы создавать временную переменную в main для хранения результата, потому что функция память под результат не выделяет. Поэтому в стандарте C++ этого нет.

    Потом, когда в С++11 ввели rvalue ссылки и перелопатили категории значений - разрешили инициализировать rvalue ссылки через prvalue.

    Поэтому работают
    const int& r1 = f();
    int&& r2 = f();
    Ответ написан
    1 комментарий
  • Почему нельзя возвращать объект по значению в non-const &?

    @Mercury13
    Программист на «си с крестами» и не только
    const struct s & ref = f();
    Этот механизм называется «продление жизни временного объекта».
    Можно написать вот так.
    struct s && ref = f();

    Главная причина преобразования временного объекта только в const T& и T&& — тонкие ошибки при суперпозиции функций.
    А именно — временный объект мы ни в коем случае не должны передать в функцию, принимающую s&.
    void modify(s& arg) { ++arg[1]; }
    
    ...
    
    modify(f());

    Мы вызвали функцию f(), её результат передали в modify, и… похѣрили.
    Ответ написан
    Комментировать
  • Почему не вызывается конструктор копирования?

    hePPer
    @hePPer
    похоже на пропуск конструктора при оптимизации
    Copy elision
    Ответ написан
    4 комментария
  • Почему память в стеке для auto переменной не резервируется с помощью rsp?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    А почему память не резервируется с помощью rsp? А если произойдет прерывание? Или тут какая-то хитрость?


    Тут какая-то хитрость под названием red zone.
    Ответ написан
    Комментировать
  • Для чего объявляется вложенная структура (или класс) перед тем, как она объявляется дружественной?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Попробуйте удалить и скомпилировать. Компилятор что говорит?
    Ответ написан
    5 комментариев
  • Почему инициализация целочисленного указателя 0 или NULL не вызывает предупреждений, хотя 0 - это целочисленная константа?

    vabka
    @vabka
    Токсичный шарпист
    int *p = 20; // warning
    Тут будет записан адрес 20, по которому лежит фиг знает что. Скорее всего при попытке разыменовать такой указатель прозойдёт SEGFAULT или что-то типа того.
    int *p = (int *)20;//ok
    То же самое. Видимо у вас не достаточно злые опции компилятора.
    int *p = (void *)20;//тем более ок и универсальнее
    То же самое.

    int *p = 0;// ok
    А тут всё ок. Вроде 0 это и есть тот самый NULL
    Ответ написан
    1 комментарий
  • Почему инициализация целочисленного указателя 0 или NULL не вызывает предупреждений, хотя 0 - это целочисленная константа?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вы присваиваете значения указателю. Указатель хранит адреса. Т.е. вы записываете в переменную адрес, на который она должна указывать. Поэтому обычно присвоение какого-то целого числа указателю - это ошибка, ведь вы не можете знать что там за адреса у вас в программе нужны. Если же вы какой-то адрес откуда-то взяли, то он и был бы уже типом указателя. Отсюда и предупреждение компилятора. Довольно часто присвоения указателю целого числа - это пропущенное разыменование указателя.

    Но 0 - исключение. Потому что нулем принято обозначать пустой, ни на что не указывающий указатель. Обычно для этого в C используют NULL, чтобы разделять число 0 и пустой указатель в коде. Но NULL, фактически и есть 0.

    Компилятор ничего не приводит, а просто игнорирует присвоение 0, ибо это нормальная ситуация.
    Ответ написан
    1 комментарий
  • Почему инициализация целочисленного указателя 0 или NULL не вызывает предупреждений, хотя 0 - это целочисленная константа?

    wisgest
    @wisgest
    Не ИТ-специалист
    0 в таком контексте — особая указательная константа для указателей в никуда, по стандартам не обязательно указывающая на нулевой адрес.
    Целочисленной константой ноль был бы в выражении
    int *p = (int)0;
    Ответ написан
    Комментировать
  • Почему возможно объявление глобальной переменной структурного типа до объявления этого структурного типа?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему возможно объявление глобальной переменной

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

    В твоём втором примере struct interval b -- это определение переменной, выделяющее для неё место на стеке. Но его можно переписать, чтобы b тоже стало объявлением, например так:
    int main ()
    {
      extern struct interval b;
      struct interval 
      {
        int first;
        int second;
      };
    }


    Возвращаясь обратно к первому примеру, struct interval b; -- это tentative definition с внешней линковкой. Стандарт (С99) говорит о нём следующее (6.9.2:2):

    A declaration of an identifier for an object that has file scope without an initializer,
    and without a storage-class specifier or with the storage-class specifier static, constitutes
    a tentative definition. If a translation unit contains one or more tentative definitions for
    an identifier, and the translation unit contains no external definition for that identifier,
    then the behavior is exactly as if the translation unit contains a file scope declaration of
    that identifier, with the composite type as of the end of the translation unit, with an
    initializer equal to 0.


    Самое важное здесь -- as of the end of the translation unit, т.е. тип объекта из tentative definition таки должен быть определён, но не до появления этого tentative definition, а до конца единицы трансляции (или раньше, если вдруг встретится определение с инициализацией этого объекта).
    Ответ написан
    1 комментарий
  • Стоит ли вовсе стремиться поступать в столичные ВУЗы?

    DollyPapper
    @DollyPapper
    Если осилите МГУ мехмат, то конечно езжайте в мск. Никакой провинциальный втуз не даст вам такой базы, сами вы тем более ее не возьмете. Математика она не программирование, чистой воды абстракция, которую самому воспринять очень тяжело. Если не планируете писать ракеты, или что-то прорывное техническое, лучше учитесь у себя. Все эти общаги это сейчас не жизненный экспириенс, а пустые за*бы. Учить сложные вещи когда вокруг полно других студентов, которые развлекаются и им похер, что вы пытаетесь освоить сложные вещи, это не гуд. Потом может получится так, что вы готовы ко взрослой жизни, можете самостоятельно позвонить в ЖЭК и перетереть с бабкой за отключенную воду или свет, но в голове у вас или пусто или большие пробелы в знаниях.
    Буквально вчера вышла статья от человека который на вечерний мехмат поступил. Почитайте.
    Ответ написан
    1 комментарий
  • Куда лучше поступать на дистанционное высшее образование?

    DollyPapper
    @DollyPapper
    Я по личному опыту скажу. Все когда рассматривают пдобный вопрос, учиться или нет, получают ровно 3 ответа. Да учиться потому что.... Нет не стоит диплом не нужен нужны знания(которые как уже выше сказали, не факт, что вы получите сидя дома за компом. Та же самая математика(которая как многие утверждают не нужна и вообще не пригодится, задумайтесь однако над тем, что программист решает задачу а не пишет код, и задачи мооогут быть как формочку заеб*нить, так и пусть и простая,но все же математика, но которую вы можете так же не осилить) Короче оочень много если. А ответ мой собственно сводится к тому, что есть еще один вариант, который изначально никто даже не рассматривает. Вы во входных данных не указали как у вас сейчас дела обстоят с написанем кода, как хороошо вы задачи решаете и прочее. Но допустим вы начинающий вкатывальщик в айти. Вот вы работаете, попутно дома учите разные предметные области. И знаете что случается у многих вкатывальщиков которые рассматривают варианты ЛИБО получаю вышку нада мне бумагу и все тут поможет потом, ЛИБО да нахер оно мне нада вот это вота, все главное навыки. А третий вариант при вводных что вы только начинаете - вы можете просто не осилить. Да представьте и такое часто случается. Рано или поздно вы можете разочароваться в себе или еще что либо, и решить что дальше не стоит пробовать. Что случается дальше? Вы ищите другую работу. А знаете какую работу можно получить без вышки? Ну все думаю прекрасно знают. А знаете как тяжело потом живется человеку который очень любит все техническое, но при этом работает в другой сфере далекой от этого, потому что не сложилось? Ну у меня например был инста депресняк года полтора. Теперь я все же работаю сис. админом, при чем довольно успешно получается. Вывод из этой простыни такой. В любом случае получайте ВО, корочка, не корочка не важно. Просто могут так карты лечь, что вы не станете программистом. А гоорбатиться за 40к, ну или даже за 90к продаваном риелтороом в МСК общаясь с ублюдками коллегами, и ублюдками клиентами не всем охото. Подумайте над этим, если у вас все толькоо начинаете и вы написали только простенький HTTP сервер на питоне. Если вы уже успешно пишете что то сложное, просто пока не освоили тонкостей даже на уровне джуна, то есть если вы уже 100% знаете что программистом вы стать способны, тогда разговор другой, и вам решать получать ВО или нет.
    Ответ написан
    Комментировать
  • Как отследить изменения в системе после установки программы?

    RUVATA
    @RUVATA
    Разработчик, гик, меломан, разгильдяй
    Существует специальная утилита SysTracer специально разработанная для отслеживания изменений в системе, осуществляя это сравнением двух «снимков системы» — до и после. В итоге получаем представленные в удобном виде данные по изменениям в трех категориях «Реестр», «Файлы», «Прочие настройки» (н/п групповые политики, трасе системных утилит aka netsh)
    (Честно вам скажу, что собирает она не всё, хотя в большинстве случаев ее достаточно)

    А уж если Вы «боритесь со защитой злом», то там используются некоторые трюки, которые обычным трейсом не запалить :)
    Иначе было бы все уж очень просто, в таком случае, самый полезный инструмент, в чем я поддерживаю участника l0calh0st,
    это Process Monitor от Sysinternals — это именно то, что нужно. (Эти ребята используют, судя по всему, некоторые не документированные возможности, Марк Руссинович знает толк :) ) И спрятать какие либо движения от этой утилиты, при правильной ее настройке — крайне затруднительно. (Хотя возможно, знаю как но не скажу — ибо нехер)

    PS: Единственное — внимательно ознакомьтесь с документацией в отношении фильтрации, так как Process Monitor by default протоколирует все события. В первую очередь Вам нужно нацелить его на ID процесса инсталятора, а так же (если он не используется в процессе установки — отключить сетевой дамп в нем очень много «мусора» сильно мешает разобраться).
    Ответ написан
    1 комментарий
  • Как дословно переводится assignment makes pointer from integer without a cast?

    @TheCalligrapher
    Дословно это можно перевести как "присваивание делает/формирует указатель из целого [значения] без [использования] явного приведения типа".

    Термин "cast" в С означает явное приведение типа. Именно явное.

    Сочетание "makes [...] without a cast" ссылается на то, что ваш оператор присваивания пытается выполнить именно неявное преобразование из указателя к целому значению.

    Все сообщение означает, что в своем коде использован оператор присваивания (assignment), правая часть которого является указателем (pointer), а левая - целым числом (integer).

    Такой код является некорректным в С, ибо язык С в общем случае запрещает неявные преобразования между целыми числами и указателями. Чтобы преобразовать целое значение к указателю в С требуется явное приведение типа, т.е. cast.
    Ответ написан
    Комментировать
  • Почему в английском такой порядок слов "Bluetooth Support Service", а в русском "Служба поддержки Bluetooth"?

    @AlexSku
    не буду отвечать из-за модератора
    Суть в том, что в английском языке определения могут выражаться как прилагательными (red pot), так и существительными (support service). Определения стоят спереди.
    В русском же прилагательные-определения стоят спереди (красный чайник), а существительные-определения - сзади (служба поддержки).
    Ответ написан
    Комментировать
  • Почему в английском такой порядок слов "Bluetooth Support Service", а в русском "Служба поддержки Bluetooth"?

    Ziptar
    @Ziptar
    Дилетант широкого профиля
    Попросту благозвучность.

    чайник красный, 1 шт.

    А это то, что входит в понятие "канцелярит". Канцелярит удобен с т.з. бюрократии любого рода - учёта, сортировки, однозначности трактовки, но совершенно неприменим в бытовой или литературной речи.
    Ответ написан
    Комментировать
  • Ноут с Windows 7 не может получить доступ к сетевой папке ПК, находящегося в той же домашней группе?

    @Drno
    Выключить брендмауэр.
    В сетевых настройках разрешить доступ без пароля к папкам.
    Заходить через ip компа, а не по имени
    Ответ написан
    4 комментария