LINUX.ORG.RU

Расскажите, как изучали C++

 , , , ,


0

4

Какие учебники использовали, ресурсы? Что порекомендуете (сложность ресурса неважна), исходя из своего опыта? Как применили язык в первый раз на практике? Какие плюсы языка для себя вывели, сравнивая с чистым C? Как долго программируете (-овали) на C++? Заучивали ли UB? Помню из лекций по cpp Ильи Мещерина постоянные странные примеры, с которыми сталкивался он на практике, наподобие «int i = 0; i < v.size(); ++i = UB», куда резольвится имя, если using namespace N внутри цикла и в N есть x, и x есть в global namespace.



Последнее исправление: shfp (всего исправлений: 1)

Какие плюсы языка для себя вывели, сравнивая с чистым C?

У С++ есть плюсы и то они все в названии.

AUX ★★★★
()

Есть глобальные конструкторы - можно заставить программу что-то сделать до запуска любых функций. В си это делается только компиляторными расширениями
Есть деструкторы - можно делать RAII, автоосвобождение памяти и т.д (в си это можно сделать компиляторными расширениями, причём не везде)
Есть полиморфизм - удобно делать векторную математику
Шаблоны и метапрограммирование. Нельзя сказать что оно прям хорошо сделано, для этого есть другие языки, но возможностей будет побольше чем в си.
Есть и минусы: паршивая стандартная библиотека без стабильного ABI (если ограничиться сишной - головной боли куда меньше), стали вставлять всякие tls и стражи без спросу (инициализация статиков начала генерировтаь бесполезную лапшу для потокобезопасности даже если функция никогда не вызовется с разных потоков)
Ну и на новые фичи лучше не смотреть - после 2017 стандарта туда такое смузи нечитабельное пихать стали, что писать на этом страшно...

mittorn ★★★★★
()

Что порекомендуете

Решать реальные кейсы — опыт придёт со временем.

thunar ★★★★★
()

Я уже давно собирался «покурить кресты», а тут такой случай — перелом конечности.

Купил книжку, первую попавшуюся, чисто чтобы въехать в синтаксис.

Далее, накатил на свободный ноут ОС Хайку (тоже давно хотел, но руки не доходили).

И понеслось.

Применяю Си++ как гик, прошу не путать со взломщиком. А именно, сфера интересов лежит в области разработки ядер. И так далее.

«Кресты» — это Си с классами.

Как-то так.

sparkie ★★★★★
()
Ответ на: комментарий от mittorn

Есть глобальные конструкторы - можно заставить программу что-то сделать до запуска любых функций.

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

GPFault ★★★★
()
Последнее исправление: GPFault (всего исправлений: 1)
Ответ на: комментарий от mittorn

Ну если с нуля, можешь плейлист на ютубе по плюсам от simple code, когда-то просмотрел все, но на практике половину всего можно было и так изучить уже в бою, в проектах. Первые 40 может уроков норм, ооп у него вроде норм, а дальше уже может и сам вкуришь. Но главное не затягивать, кажется там около 200 уроков, или чуть меньше, но половину можно просмотреть на 2х

chebo7
()
Последнее исправление: chebo7 (всего исправлений: 1)
Ответ на: комментарий от sparkie

«Кресты» — это Си с классами.

Фи, прошлый век. Надо так:

«Кресты» — это Си с policies.

ant1 ★
()
Ответ на: комментарий от GPFault

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

firkax ★★★★★
()

Какие учебники использовали, ресурсы?

Google и Stackoverflow.

Как применили язык в первый раз на практике?

Qt прога на QtWidgets. Сразу пришло понимание что без таких библиотек плюсы лучше не юзать.

Какие плюсы языка для себя вывели, сравнивая с чистым C?

Самый большой плюс - это дженерики. Без классов жить можно, без дженериков - сложновато. А ну ещё, лямбда-функции, но это косвенно тоже относится к дженерикам.

Skullnet ★★★★★
()
Ответ на: комментарий от GPFault

Согласен, потому предпочитаю избегать этого механизма. Но тем не менее это возможноость реализованная компиляторами, ОС, линкерами, при этом доступная штатно в C++, но не в C

mittorn ★★★★★
()
Ответ на: комментарий от firkax

Никогда не пытайтесь учить программирование по видеороликам.

Это, наверное, у всех по-разному. Но я не понимаю, как можно воспринимать обучающую информацию в аудиовизуальном формате. К меньшей плотности полезных данных, заложенной в сам формат, добавляется ещё и то, что любая лекция всегда включает долю импровизации, которая размывает смысл ещё сильнее. И даже если слушать запись, действия, необходимые для повторного воспроизведения, требуют больше усилий, чем перечитать предложение или перелистнуть страницу.

Текстовый формат здесь заметно выигрывает. Информация в письменном виде значительно плотнее сама по себе, к тому же зачастую в книге автор несколько раз перечитывает предложения, внося правки на разных этапах. Чтобы воспроизвести повторно непонятный фрагмент, нужно всего лишь перечитать его, в крайнем случае – перелистнуть страницу, а не терять концентрацию, чтобы тыкать мышкой/жать по клавишам.

html-kernel
()

Из учебников - cppreference, что-то спрашивал тут, остальное гуглил по мере надобности. Применил при портировании кусков кода игры с windows на linux. Понравились auto и компактная запись циклов из 17-го стандарта. Где-то пол-года плотно с ним работал, но больше к языку так и не вернулся. Из недостатков - RAII и шаблоны знатно попили крови - по мне это одна из неудачнейших идей в плюсах вообще. Туда же и полиморфизм - переопределять базовые арифметические операции это надо додуматься, блин - когда в одной строке простой плюс может обозначать разные действия - это очень ломает мозг. А, и ещё отлавливая баги узнал о полезнейшей вещи которую использую по сей день - ASAN/UBSAN, работая с сями как-то не было надобности в санитайзерах, хватало валгринда.

Да и учить язык сам по себе - дурная затея. За пределами браузеров, игр и некоторого количества десктопных программ (и то там чаще Qt) он не используется. Язык надо учить либо если есть легаси на нём, либо под задачу - если программа предполагает большую сложность и требует высокого быстродействия.

eagleivg ★★★★★
()
Последнее исправление: eagleivg (всего исправлений: 1)
Ответ на: комментарий от html-kernel

Нет, не «по-разному». Точнее, если кто-то воспринимает текст хуже чем видеоролик - ему нечего пытаться программировать. Речь именно про ролик, нормальная лекция имеет свои плюсы (но всё равно сама по себе будет недостаточна, всё равно требуется текстовый формат).

firkax ★★★★★
()

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

tcpfinhello
()

Какие плюсы языка для себя вывели, сравнивая с чистым C?

Главными возможностями C++ являются

  • деструкторы. Такая функция, которая при окончании скоупа неявно вызовется сама. На этом построено 100500 всякой автоматизации и всё с приставкой «smart».
  • шаблоны. Возможность накатать обобщённый код для заранее неизвестного типа или поуправлять компилятором. И на этом навёрнуто тоже 100500 всякой магии.

Тащемдо, это базовая база плюсов, всё остальное - производное от этого.

ООП, RAII и прочее такое за супервозможности не считаются, потому что костылями это было достижимо и в сишечке, а вот эти штуки выше были нереальны.

tcpfinhello
()
Последнее исправление: tcpfinhello (всего исправлений: 2)

Заучивали ли UB?

Нет, это достаточно очевидная фигня, если голова хорошо работает, то есть умеет последовательно на уровне ассемблера понимать и исполнять то что написано пошагово, если есть понимание что во что компилируется. Плюсы же типа из семейства сишного, то есть для людей которые любят железо, низкоуровневое что-то, оптимизации там всякие, хардкор и жесть. Предполагается, что писателю на крестах будет любопытно во что компилятор это компилирует. Ясно же, что проверка в for выполняется перед каждой итерацией и если внутри итерации вы воздействовали на состояние v, то оно могло поменяться, но вообще это не UB. UB достаточно спорная штука: некоторые называют UB то, что вполне детерминировано, просто почему-то рвёт им шаблон.

«using namespace» юзать тон плохой, это типа как пейсать код с макросами. Плохой потому что происхоит замес чего-то в другой неймспейс, может быть путаница, лучше явно написать std::string.

tcpfinhello
()
Ответ на: комментарий от firkax

Иногда есть необходимость: подмена системных функций и сохранение указателей на оригинальные (RTLD_NEXT) в функции с __attribute__((constructor)).

shdown ★★
()

У меня так получилось, что первый язык, который я выучил, это бейсик для дельта-с. В школе тоже был вариант бейсика, Quick Basic. Еще, на кассете, которая прилагалась к дельта-с, был паскаль. И если бэйсик я учил по инструкции, которая шла с дельта-с, то с паскалем мне пришлось брать книги в библиотеке.

Позже, когда в 11-м классе школы, у меня появился первый нормальный компьютер, я первым делом стал пробовать примеры из книжек по паскалю. Потому что на дельта-с все-таки не все можно было запустить, там паскаль был свой, кастрированный. К первому курсу универа я уже осил Делфи.

С си и С++ я познакомился именно в универе уже. Помнится, эти языки мне не давались так легко. После паскаля и делфи все казалось неудобным. Учась в магистратуре, я поступил в НИИТ, нижегородский институт информационных технологий на курс именно по С++. К тому времени, я уже мог сносно на нем кодить. Курс просто собрал разрозненные знания и я получил сертификат для работы.

Так что, терпение и труд все перетрут. Язык интересный. Стоит того, чтобы поломать мозги.

hibou ★★★★★
()
Ответ на: комментарий от Reset

Читай труды отцов основателей: Страуструп, Александреску, Саттер

Из зубров Майерса незаслуженно забыли.

bugfixer ★★★★★
()

практики и просто понимание индексов массива - т.е. какую нить простою регистро0стековую модель машины ну там что машина с магазином кручее КА которой кручее машина сRAM

иишница ща вполне неплохое отличие поинтер(не bird dog) и индекса - типо указатель это абсалютный якорь - а индекс типо перемеащемый(от базы) токмо сразу вспомнилась сегментная модель x86 и ад кутежа far vs near pointer

достаточно помнить что С++ не хаскель для этого полезно листануть Дизайн и Философию Страуструппа - чисто для понимания почему трейдофы коньюктурны

qulinxao3 ★☆
()
Ответ на: комментарий от GPFault

а это вопрос модульности

(вроде очередного бастарда в текущих версиях ещё не закопали и вроде успешно гальванизируют )

qulinxao3 ★☆
()
Ответ на: комментарий от Reset

не, конечно прочитать их в любом случае полезно, но всё же лучше изначально использовать RAII и прочие новые смузи

s-warus ★★★★★
()
Ответ на: комментарий от mittorn

Ну и на новые фичи лучше не смотреть - после 2017 стандарта туда такое смузи нечитабельное пихать стали, что писать на этом страшно

в текущем речекряке - для олдов-фултстеков «новое нечитабельное» как и для джунов полезно - а вот мидлам оно вредно

олдам - для добавлении ещё болших трюков в их терс код - для джунов - что бы быть дальше от машины

qulinxao3 ★☆
()
Ответ на: комментарий от qulinxao3

для этого полезно листануть Дизайн и Философию Страуструппа - чисто для понимания почему трейдофы коньюктурны

Два чая за дизайн и философию. Рейшенал на максималках (чего всегда не хватает буквально везде).

yax123 ★★★★★
()

Познакомился с плюсами в школе, поначалу ничего не понимал. Несколько раз прочитал Лафоре, разобрался с базовыми вещами, стало гораздо легче. Параллельно пробовал другие языки программирования, писал маленькие программки. Устроился на работу, требовалось писать на плюсах. В процессе узнал много нового, часто обращался к cppreference. Главное - практика и реальные задачи

tache
()

Треды/срачи царя здесь на лоре и в тг

keyzd
()
Ответ на: комментарий от shdown

Напиши полный код примера, который по-твоему нельзя переделать без неявных инициализаторов, а то не совсем понятно что ты хочешь добиться.

firkax ★★★★★
()
Ответ на: комментарий от sparkie

Вообще, интерес к «крестам» начался с АПИ по оффтопуХР Даже книг прикупил энное количество по теме.

sparkie ★★★★★
()
Ответ на: комментарий от firkax
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

static void full_write_s(int fd, const char *s)
{
    size_t ns = strlen(s);
    size_t nwritten = 0;
    while (nwritten < ns) {
        ssize_t w = write(fd, s + nwritten, ns - nwritten);
        if (w < 0) {
            break;
        }
        nwritten += w;
    }
}

static int (*orig_fflush)(FILE *f);

__attribute__((constructor))
static void initialize(void)
{
    *(void **) &orig_fflush = dlsym(RTLD_NEXT, "fflush");
    if (!orig_fflush) {
        full_write_s(2, "dlsym() failed\n");
        abort();
    }
}

int fflush(FILE *f)
{
    full_write_s(2, "fake fflush() called\n");
    if (!f) {
        return 0;
    }
    return orig_fflush(f);
}

int main()
{
    lua_State *L = luaL_newstate();
    if (!L) {
        fprintf(stderr, "luaL_newstate() failed.\n");
        return 1;
    }
    luaL_openlibs(L);
    int r = luaL_dostring(L, "f = io.popen('echo hello'); s = assert(f:read()); print(s:upper())");
    if (r != 0) {
        fprintf(stderr, "luaL_dostring() failed.\n");
        return 1;
    }
    fflush(stdout);
    return 0;
}

Должно выводить

fake fflush() called
HELLO
fake fflush() called
Собирать с $(pkg-config --cflags --libs lua5.1).

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от shdown

Нужно ещё #define _GNU_SOURCE и -ldl.

Содержимое функции initialize() переносишь в начало main(), функцию убираешь, всё работает как и ожидалось.

Проблемы тут могут возникнуть только если кто-то в другом месте (включая какое-то so) встроил свой код перед началом main и он вызовет fflush. Но от этого проблемы могут возникнуть и в твоём коде, ведь неизвестно чей хук запустится раньше.

А чтобы проблем не было - надо этот код вставить в подменённый fflush().

int fflush(FILE *f)
{
    if(!orig_fflush) {
       *(void **) &orig_fflush = dlsym(RTLD_NEXT, "fflush");
        if (!orig_fflush) { full_write_s(2, "dlsym() failed\n"); abort(); }
    }
    full_write_s(2, "fake fflush() called\n");
    if (!f) return 0;
    return orig_fflush(f);
}

тут правда тоже может возникнуть некрасивая ситуация из-за мультитреда (хотя вроде без последствий, просто двойное исполнение кода инициализации этой переменной), и чтобы её тоже избежать можно ещё навернуть костылей, хотя вроде можно и не избегать.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 4)
Ответ на: комментарий от firkax

тем не менее, много софта вызывает dlopen из других потоков.
Иногда это приводит к дедлоку

mittorn ★★★★★
()
Ответ на: комментарий от firkax

Никогда не пытайтесь учить программирование по видеороликам.

кресты и видосы - созданы друг для друга

olelookoe ★★★★
()
Ответ на: комментарий от shdown

А это без разницы. Функция fflush() в моём примере полностью автономна, не важно кто, когда и откуда её вызывает.

Или если ты про то, что библиотека вообще хочет сделать что-то на старте? Тогда да, придётся эти штуки использовать. Но вообще это не очень хороший приём - выполнять на старте библиотеки какой-то код. Лучше выполнять его через функцию типа my_lib_init(), который программа может вызвать когда посчитает нужным.

firkax ★★★★★
()
Ответ на: комментарий от qulinxao3

Спорно, очень спорно. Большинство нововведений - новая лапша в стандартной библиотеке, которую олды и сами в состоянии написать.
Остальное - разрозненный хлам

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

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

Глупый вопрос. А зачем что-то делать до первых строк main()? какой в этом философский смысл? (имеем ввиду, что типичный C код - это чуть «слаще» macro ассемблера)

Shadow ★★★★★
()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от Shadow

Это вообзе большой вопрос, зачем такую функциональность изначально завезли в C++. Возможно пытались усложнить жизнь старым системам когда-то, а может в каком-то языке это было и c++ решил не отставать. Но это позволило иметь не-constexpr инициализаторы у глобалок

mittorn ★★★★★
()
Ответ на: комментарий от Shadow

Глупый вопрос. А зачем что-то делать до первых строк main()? какой в этом философский смысл? (имеем ввиду, что типичный C код - это чуть «слаще» macro ассемблера)

Ну типо чтобы main() была поменьше. Хотя можно было

void initialize_something() {
}

int main(const char **argv, int argc) {
  initialize_something();
}
tcpfinhello
()

Первый язык был BASIC на «Правец 8Д» в каких-то там кружках в мелком возрасте. Пока там народ пытался в игры играть, я понял что очень люблю печатать и печатал поначалу всякий бред, а потом выдавал на BASIC дикие простыни текста играющие мелодии на память. Препод сказал, что это какая-то жесть, не только лишь у всех столько усидчивости чтобы подобное налабать.

Потом я пришёл в универ, а там была на первом крусе «информатика» и всем раздали книгу по С Подбельского. Наверное всё-таки это был С++. Ну и понеслось по трубам, мы преподу все сетевые диски тогда файлами по 4 гигабайта засрали! Ух как мы там изгалялись, выжали из вычислительных машин последнее. Там были какие-то 486 девайсы с большими IBM клавиатурами и кинескоповыми мониторами. Ещё помню в те времена вирусы активно ходили на дискетах, даже BIOS заражало. Потом я как-то увлёкся ассемблером и написанием своей OS на нём, оно грузилось с дискеты и читало FAT12, но потом я узнал что MenuetOS уже написан и что существует линкус где вообще всё на сишечке и никто мозг не насилует.

tcpfinhello
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.