LINUX.ORG.RU

Ответ на: комментарий от UVV

* относится именно к типу, а не к переменной

Если бы тут она «относилась» к типу, все три переменные были бы указателями, я вот о чём. Ессно char и char* - типы разные, но * - «индивидуальная» для каждого имени переменной

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

Если бы тут она «относилась» к типу, все три переменные были бы указателями, я вот о чём. Ессно char и char* - типы разные, но * - «индивидуальная» для каждого имени переменной

Безусловно. Из этого следует, что она относится к типу, но нотация неочевидна, да.

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

Стили программирования на С и С++ сильно различаются. Если говорить о концепциях, то для С++ их придётся освоит по-более чем для С и С тут не поможет. Кроме С-style casts в С++ не используются (гораздо меньше используются):

  • if + goto + единственная точка выхода из фунции, вместо них - RAII + исключения;
  • нетипизированные указатели, вместо них - шаблоны.

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

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

Нотация очевидна, если читать char *var не как «var имеет тип char *», а как «*var имеет тип char». Просто это слегка неинтуитивно.

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

Нет никакой практики, которая настолько въелась в мозг, что ее будет сложно выкинуть, человек не понимает базовых вещей. В C++ он просто утонет. В нем любой утонет, даже если до этого ты знал Си, знал Java, знал Haskell и Common Lisp, это с лихвой перекрывает все эти «концепции» используемые в C++, но писать на нем нормально можно будет не через неделю и даже не через месяц.

Я не могу назвать не одной абстракции из крестов, которая не течет, ими просто невозможно пользоваться как черными ящиками. Обязательно нужно знать как и что сделано и ПРЕДУГАДЫВАТЬ коллизии между ними. Освоение C++ включает в себя освоение Си.

Kuzy ★★★
()

Жесть. И как это я сам не догадался зарегистрироваться и задавать тупейшие вопросы по C++!

anonymous
()

Тебе уже сказали, что либо

std::vector<std::string> *vecstr;
vecstr = new std::vector<std::string>();
vecstr->push_back("vector");

Т. е. выделить память для указателя на вектор (т. к. описание указателя само по себе память не выделяет). Либо использовать сразу объект вектор, а не указатель на него:

std::vector<std::string> vecstr;
vecstr.push_back("vector");

И ещё: в заголовке (в h-файле) указывают прототипы функций, структуры и классы, а переменные и указатели объявляют в cpp. Так что h'ник тут лишний.

И самое главное: как следует разберись с указателями/ссылками/массивами. Пока есть малейшее подозрение, что в этой части понятно не всё и/или не до конца, двигаться дальше бесполезно, что наглядно продемонстрировал твой нынешний пост.

А касательно сложности Страуструпа: мне он в своё время не показался таким уж сложным. В любом случае это лучшее из написанного по Си++, т. к. что рекомендую напрячься и осилить.

aureliano15 ★★
()
Ответ на: Я за бан от anonymous

А что не так? По-моему человек взялся за ум, пытается читать Страуструпа, а не ищет методичек типа «С++ за пять минут»? Ясно, что у него возникает масса вопросов, которые могут показаться наивными людям, уже изучившим язык. Ну так надо помочь, а не банить и не троллить. Ведь Си++ - непростой язык, а указатели - наверно самая сложная его часть, вызывающая массу проблем, и не только у новичков (что мы можем видеть каждый раз, когда во вполне профессиональном ПО снова и снова появляются утечки памяти и уязвимости, связанные с переполнением буфера).

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

а переменные и указатели объявляют в cpp.

А в случаях, когда нужен один заголовок со всеми переменными для разных классов инклюдящих этот заголовок, каждый класс из которых может изменять значение переменной?

ioexception
() автор топика
Ответ на: комментарий от ioexception

А в случаях, когда нужен один заголовок со всеми переменными для разных классов инклюдящих этот заголовок

В этом случае в заголовке надо написать extern std::vector<std::string> vecstr; Ключевое слово extern не создаёт объект/переменную, а просто сообщает, что она существует. Одновременно в одном из cpp-модулей (но только в одном!) надо объявить переменную: std::vector<std::string> vecstr; иначе (если её вообще нигде не объявить) будет ошибка на этапе линковки о том, что переменная vecstr не найдена. Если же в нескольких модулях надо объявить разные переменные с одним и тем же именем, то следует использовать ключевое слово static перед обявлением переменной: static std::vector<std::string> vecstr; Это тоже делается в cpp-модуле, слово static ограничивает область видимости текущим модулем. Впрочем, вместо static лучше пользоваться пространствами имён namespace. Кстати, static применительно к глобальной переменной, к локальной переменной и к переменной-члену класса обозначает разные вещи, как и в живых языках одно и то же слово в зависимости от контекста может трактоваться по-разному.

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

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

Связано это с тем, что большие программы могут состоять из десятков и сотен модулей. Обычно при сборке релиза они перекомпилируются полностью, но во время отладки в этом нет нужды, т. к. можно компилировать только модифицированные модули, иначе процесс компиляции и сборки может занять очень много времени (например, OpenOffice компилируется несколько часов). Но для этого переменные и настоящие (т. е. вызываемые ассемблерной командой call, а не inline) функции должны находиться в этих самых модулях, а не в заголовках.

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

Кроме c-style кастов я, не особо могу придумать, что в C++ из Си не используется.

как минимум, malloc(), etc обычно стараются не использовать

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

Ему нужно сессию/лабу сдать или что-то типа того, а не язык изучить.

ага. А потом он диплом получит, и пойдёт работать. Может не нужно?

emulek
()
Ответ на: комментарий от yoghurt

Если бы тут она «относилась» к типу, все три переменные были бы указателями, я вот о чём

теперь подумай про const. Я тоже пишу char* var…;

emulek
()
Ответ на: комментарий от aureliano15

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

мы про C++, в нём макросы не нужны. Есть inline, есть шаблоны.

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

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

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

примеры можно?

Да ради бога! :-)

Пример 1: допустим, есть некая функция, которая выводит на экран и/или в лог некую отладочную информацию: код ошибки, текстовое сообщение, а также модуль и строку, где произошла эта ошибка. Вызывать такую функцию нам придётся как-то так:

errmsg(nerr, szmsg, __FILE__, __LINE__);

Естественно было бы опустить __FILE__ и __LINE__, которые вставляются во все вызовы функции без изменений. Но если мы укажем их параметрами по умолчанию в прототипе даже inline-функции, то препроцессор вычислит один раз место, где объявляется эта функция и везде будет выводить нам именно этот h'ник и эту строку в нём, что нам совершенно не нужно. Если же мы создадим обёртку в виде макроса:

#define macroerrmsg(nerr, szmsg) errmsg(nerr, szmsg, __FILE__, __LINE__)

и будем вызывать этот макрос, то всё будет Ok.

Пример 2: допустим в тех же отладочных целях мы выводим имя и адрес функции, интересующей нас. Можно написать что-то вроде

printf("%s: %p", "func", func)

Но не хочется одно и то же слово набирать дважды: в кавычках и без. С помощью макросов эта проблема легко решается:

#define strf(f) # f
#define printfinfo(f) printf("%s: %p.\n", strf(f), f)

Вызывая printfinfo с одним аргументом - именем нужной функции без кавычек, мы получаем на выходе и её имя, и адрес.

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

aureliano15 ★★
()

язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан язабан

anonymous
()
Ответ на: комментарий от yoghurt

const, к слову, может по разные стороны от звездочки стоять ;)

да, я о том и говорю. Смысл-то разный, куда const воткнули!

emulek
()
14 марта 2017 г.
Ответ на: комментарий от backburner

Когда '*' относится к переменной, это уже разыменовывание.

В объявлении переменной это тоже разыменование:

std::vector<std::string> *vecstr;
значит «разыменованный vecstr имеет тип std::vector».

Поэтому звёздочка работает так, как она работает, при объявлении нескольких переменных. Ты говоришь, что есть тип T. А потом говоришь, это тип у переменной или у разыменованной переменной.

Так-то!

anonymous
()
Ответ на: комментарий от UVV

А не всё ли равно, как трактовать? Если хочешь можешь обозвать указатель модификацией переменной (а типа или нет не суть важно). Суть от этого не изменится.

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

Тьфу, аноним, вынудил меня некропостингом заниматься.

peregrine ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.