Вы видите копию треда, сохраненную 4 ноября 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
И хрюкала толпа крестоблядей,
Пытаясь среди макросов завалов
Найти тот, что вонял бы пострашней.
Я ощущал, как препроцессор смрадом,
Мне лютым, но благим для их ноздрей,
Исходит. С их загоном мерзким рядом
Я поравнялся, и моим глазам
Предстали рывшиеся в коде за оградой,
Как будто взятом из отхожих ям.
Там был юнец, так густо отягченный
define'ов слоем, что уже и сам
Не смог понять бы кал, им испражненный.
Литература:
Для нюфань:
Учебники для начинающих. Все примерно одинаковой годноты, читать имеет смысл только какой-нибудь один, который больше приглянется.
Стэнли Липпман, Жози Лажойе и Барбара Му - Язык программирования C++ (2014) - https://goo.gl/kVaela
Стивен Прата - Язык программирования C++ (2012) - https://goo.gl/z7kA8u
Бьерн Страуструп - Программирование. Принципы и практика использования C++ (2011) - https://goo.gl/nAFUXa
<устарело> Герберт Шилдт - C++. Базовый курс (2010) - https://goo.gl/qMLAFl
<устарело> Роберт Лафоре - Объектно-ориентированное программирование в C++ (2004) - https://goo.gl/QvjR6x
Учимся не писать говнокод:
Книги про основные подводные камни для тех, кто осилил предыдущий пункт. Следует пролистать все.
Скотт Мейерс - Эффективное использование C++ (2005) - https://goo.gl/wsDXGz
Скотт Мейерс - Наиболее эффективное использование C++ (1996) - https://goo.gl/tHa0tO
Скотт Мейерс - Effective Modern C++ (на ангельском) (2015) - https://goo.gl/uImH0J
Скотт Мейерс - Эффективное использование STL (2002) - https://goo.gl/QtS8Dc
Герб Саттер и Андрей Александреску - Стандарты программирования на языке C++ (2005) - https://goo.gl/Cpk4YR
Наиболее детальные описания языка:
Бьерн Страуструп - Язык программирования C++ (на ангельском) (2013) - https://goo.gl/XkAiOX
<устарело> Бьерн Страуструп - Язык программирования C++ (2010) - https://goo.gl/iZBDiV
Стандарт C++14 (на ангельском) - https://github.com/cplusplus/draft/raw/master/papers/n4140.pdf
Последняя на данный момент версия черновика стандарта C++17 (на ангельском) - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4527.pdf
Тонкости языка (для гурманов):
Андрей Александреску - Современное проектирование на C++ (2002) - https://goo.gl/e1V5BC
Герб Саттер - Решение сложных задач на C++ (2002) - https://goo.gl/iWaa6S
Герб Саттер - Новые сложные задачи на C++ (2004) - https://goo.gl/4nn512
Также для легкого чтения подойдет книжка c историей создания C++:
Бьерн Страуструп - Дизайн и эволюция C++ (1994) - https://goo.gl/FqbPwo
Отдельные аспекты:
Читать по необходимости.
Энтони Уильямс - Параллельное программирование на C++ в действии (2012) - https://goo.gl/qJfBkD
Николаи Джоссатис - C++. Стандартная библиотека (2012) - https://goo.gl/PEyiMH
Дэвид Вандевурд, Николаи Джоссатис - Шаблоны C++. Справочник разработчика (2003) - https://goo.gl/0M4NpG
Роберт Седжвик - Фундаментальные алгоритмы на C++ (2001) - https://goo.gl/4jwxSl (части 1-4), https://goo.gl/yDuQgG (часть 5)
Ариндам Мукерджи - Learning Boost C++ Libraries (на ангельском) (2015) - https://goo.gl/b0gPN1
Ссылки:
Годный блог, в котором все просто и понятно тян не нужны кококок борщ - http://alenacpp.blogspot.ru/
Краткие описания библиотечных функций и контейнеров - http://ru.cppreference.com/w/
Блог Герба Саттера (на ангельском) - http://herbsutter.com/
Блог Скотта Мейерса (на ангельском) - http://scottmeyers.blogspot.ru/
Куда писать код:
Под шиндошс удобно использовать IDE Microsoft™ Visual Studio®. Базовую версию (2015 Community) можно бесплатно скачать, следуя инструкциям с этой страницы: https://www.visualstudio.com/ru-ru/products/free-developer-offers-vs.aspx. Чтобы начать писать код, нужно запустить Visual Studio, кликнуть "Файл - Создать - Проект - Пустой проект", после создания кликнуть слева правой кнопкой мыши по пункту "Файлы исходного кода", выбрать "Добавить - Создать элемент - Файл C++". Свои хэллоуворлды писать в этот файл, в дальнейшем можно добавить другие файлы и хедеры. Чтобы скомпилировать и запустить проект, нужно нажать "Сборка - Собрать решение", а затем "Отладка - Запуск без отладки".
Под *nix, как правило, уже предустановлен компилятор gcc (если нет, используй sudo aptitude install gcc), так что достаточно сохранить хэллоуворлд, набранный в текстовом редакторе, и выполнить g++ helloworld.cpp и ./a.out. Но удобнее установить какую-нибудь IDE, например, Code::Blocks (sudo aptitude install codeblocks) и работать в ней.
Можно также не устанавливать ничего, а запускать свои хэллоуворлды на http://ideone.com, выбрав в левом нижнем углу язык C++14.
Софт и библиотеки:
IDE, призванная похоронить Visual Studio пока не особо получается. Удобные свистелки и перделки присутствуют. Тормоза и баги пристуствуют. Кросплатформенность присутствует - https://www.jetbrains.com/clion/
Статический анализатор, который умеет находить в коде ошибки и неоптимальные места. Швабодный. Есть плагин для Visual Studio - http://cppcheck.sourceforge.net/
Детектор утечек для Visual Studio. Предельно прост в прикручивании - https://vld.codeplex.com/
Гугловские утилиты для контроля корректности кода - https://github.com/google/sanitizers
Гугловский фреймворк для автоматизации тестирования - https://code.google.com/p/googlemock/
Йоба-набор библиотек, способный удовлетворить даже самые скотские фантазии - http://www.boost.org
Библиотека для удобной высокоуровневой работы с сетью - https://casablanca.codeplex.com
Простая в обращении библиотека для работы с графикой и аудио - http://www.sfml-dev.org
И многое другое - http://en.cppreference.com/w/cpp/links/libs
Памятка:
Вопросу по синтаксису идут на хуй.
Лабы идут на хуй.
"Как мне сделать Х на чистых крестах без библиотек" идут на хуй.
Все идут на хуй.
Хейтер сосет члены на пару со своей мамашей.
Тег [code] работает через жабаскрипт-костыль: https://github.com/ololoepepe/MakabaCode
Старший брат: >>518562 (OP)
Предыдущий: >>546742 (OP)
> стандартный комитет
> нестандартный комитет
>Я карочи скачал фаел с ентернета а тма камп бабах ебах брат умир кишки кота распидарасила памагите плиз. Что теперь делать?
а) Поподробнее, пожалуйста. Какая именно ошибка? Где создавал проект? Зависимости в его св-х указал?
б) >>qt4-dev-tool
А чо qt2 не скачал сразу-то?
СИ толь в вузе изучал, курсачи по Корману писал.
Сейчас пхп быдо кодер, вот хочу освежить память и сохить на собеседование в СИ контору.
Ты бы определился, Си или С++ тебе нужно знать.
>либы Qt в своем быдлокоде
нахуя?
>Решил сегодня попробовать кресты
>Поставил qt4-dev-tool
Приходи к нам пожже
>Блджад, покурил стандарт и таки да. Мне всегда казалось, что это unspecified. Энивей, "most existing implementations of C++ ignore integer overflows".
СУРЬЁЗНО? Я может неправильно понял? У меня есть код, в котором (не один раз) встречаются (упрощённо) следующего вида циклы for:
>const std::size_t size_t_max = static_cast<std::size_t>(-1);
>for (std::size_t i = size_t_max; count < n; ++count)
>{
>array[++i] = count;
>array[++i] = count;
>array[++i] = count;
>array[++i] = count;
>}
Я хочу проходить по 4 значения array, присваивая им текущее значение счётчика. Array состоит из четырёх миллионов значений. За счёт ++i вместо i++ я хочу выиграть миллисекунду, я жадный.
В самую первую итерацию в первый инкремент у меня происходит переполнение i с size_t_max до предполагаемого нуля. И в MSVS Express 2013 это работает ровно так, как я и ожидал -- обращается к array[0] и т.д. Тем не менее, вопросы:
std::size_t i = static_cast<std::size_t>(-1);
++i;
1) Это UNDEFINED behaviour? да/нет
2) Это unspecified behaviour? да/нет
3) Можно привести прямую цитату из стандарта, разъясняющую этот момент?
В unsigned арифметике оверфлоу - не UB, а просто по модулю сокращается. В signed - UB
Проект нигде не создавал, просто создал файлик в блокноте, и скормил его g++. Просто командой g++ blah.cpp -o blah
Ошибка: main.cpp:2:19: fatal error: QString: No such file or directory
>>555241
>Нахуя?
Хочу один свой студентопроект перенести с жабы, на кресты. Кресты нихуя не знаю, надо аналог жабовского BufferedImage. В кутях же вроде много всяких полезных библиотек, хотел задействовать.
Господибоже. Конпелятор должен сам пойти и найти твои qt тулзы на пеке? Да, сорри, забыл что ты явамакака, бывает.
Лёгкий путь решения проблемы: поставь Qt creator, настрой (если ставил не с пакетом сдк) и создавай проекты в нём.
Хардкорный путь: дрочи мейкфайлы, цланги и прочее говно.
>перенести с жабы, на кресты. Кресты нихуя не знаю
сасируй члены тогда, как раз работа для жабодауна
Когда выделяется память под объект, также сохраняется инфа про размер выделеного блока. Тоесть ты создал 1000 объектов, тебе нужно также сохранить 1000 размеров этих объектов. На практике это выглядит так что на объект выделяется больше памяти чем он занимает, в зависимости от способа раздела памяти, каждая аллокация с пощью new может потреблять, к примеру, еще +16 байт памяти на служебную инфу. При этом если объекты твоего класса имеют постоянный размер, ты можешь сохранить этот размер в статической памяти, и использовать при деаллокации, тоесть не нужно хранить размер для каждого инстанса отдельно. Я так понимаю это для пердолинга с кастомными аллокаторами, если использовать стандартный способ (непереопределенный new) то там похуй на размер, у системы свой способ помечать выделеные куски памяти и всяких там грязных пейзан допускать к выделению она не будет.
Разве размер обьекта не всегда одинаковый?
Ты же не можешь в обьекте обьявить полем массив изменяющегося размера, ты можешь обьявить указатель на него, но не сам массив.
Нет. Вроде не с чего памяти освобождаться, если ты ее сам через new выделил и никаких освобождений не делал. Если конечно под контейнером ты имеешь в виду именно какой-нибудь std::vector или std::list, а не какой-нибудь std::unique_ptr
Шел бы ты нахуй, петушок. Я солист митол-группы и работаю тимлидом в компании - лидере отрасли.
И какова же эта разница, пидарас? учитывая, что они находятся в одном и том же пространстве памяти в хуе86 на современных ОС
Не обессудьте, до этого не работал, и не приходилось использовать. На собеседовании сказал, что понимаю постольку-поскольку и могу подтянуть.
Тебе подойдет mocha.
Залечите, помогают ли rvalue/xvalue оптимизировать код.
assert.h используй, преемственность поколений должна быть! Говнотесты можно писать без всяких фреймворков, на коленке. Без задней мысли берешь экземпляр класса и тестируешь.
За годные фреймворки - не знаю, сомневаюсь что они что-то сильно облегчают.
Угу, смотри std::move
При грамотном использовании помогают.
Неправда, на простых ассертах слишком мучительно тестировать. И так написание юнит-тестов это монотонное скучное говно, сам б-г велел его облегчить каким-нибудь йоба-фреймворком.
>>555599
Мне очень нравится google test, на него в шапке есть ссылка на самом деле у них есть google test и более продвинутый google mock, в который входит google test. Куча свистелок и перделок простые и понятные моки, ассерты с разнообразными условиями, рандомизация порядка выполнения тестов, вывод с подсветкой, в общем, шоб я так жил.
Еще хвалят boost::test, но вроде в нем меньше фич он старше гугловского гораздо.
У ТЕБЯ КАРТИНКА НЕПРАВИЛЬНАЯ
ДОЛЖНО БЫТЬ ТАК:
РАЗРАБОТЧИКИ КОМПИЛЯТРООВ ССУТ НА КОМИТЕТ И СТРАУСТРУПА
РЯДОМ ПРОРАМИСТ ИГРАЕТ С ЩЕНКОМ ПОДПИСАНЫМ "ЯЗЫК С"
Почему нет автоматического освобождения памяти в конце скоупа? Ведь объект не виден за пределами скоупа, где он создан, соответственно, оттуда его не удалишь.
Што? Как это не виден? Он виден везде где есть ссылка на него.
Выделяй в стеке, если хочешь удаление
Наверно, не ссылка, а указатель?
>Выделяй в стеке, если хочешь удаление
В стеке при помощи malloc / new? Это как? Если что, речь о неизвестном на этапе компиляции значении размера массива, например, это значение получается в ходе долгих вычислений, и/или пользователь через std::cin вводит это значение.
Мне не костыль (который, кстати, я уже и так использую) интересен, а причины, по которым дизайн языка такой, какой он был до умных указателей.
Моё предположение, что ручное управление памятью было и есть в целях скорости. Но интересно узнать правильный ответ.
>Почему нет автоматического освобождения памяти в конце скоупа?
Есть. Твой указатель автоматически выделяется на стеке и автоматически удаляется при выходе из скоупа.
Байтоебы. Не течет. Джаваблядки соснули. Stop the world. Мамку по значению. Сборщик уберет. насрал под себя. Неосиляторы. MOV AX, AX. Велосипеды. Указатель на указатель.
>Почему нет автоматического освобождения памяти в конце скоупа?
Есть во всех языках. При выходе из скоупа удаляются все локальные переменные. В С++ кроме этого вызываются деструкторы объектов.
Потому что разработчик не всегда хочет, чтобы в конце скоупа освобождалась вся память, выделенная в этом скоупе по malloc, new. Если бы так было, то не было бы способа создать в куче объекты, переживающие скоуп.
Умные указатели и вправду далеко не везде нужны, и они замедляют программу. Они нужны, когда нужна семантика владения объектом. За освобождение памяти/выделение на стеке/переживание скоупа тебе уже толково объяснили.
Добавлю только - что на область памяти может быть дохрена указателей откуда угодно(в т.ч. из других объектов на куче/стеке/статическом хранилище). И поэтому нельзя удалять объект, пока на него есть указатели - иначе указатели "повиснут"(будут указывать на удаленную "битую" память).
>Умные указатели и вправду далеко не везде нужны, и они замедляют программу
Это в общем случае неправда. У std::unique_ptr нет оверхеда.
Тут мне остаётся только согласиться и пожать плечами, ибо unique_ptr вроде и умный(хотя и не умеет в общий ресурс), а счётчик ему не нужен.
Ну надо было сказать просто shared_ptr, а не абстрактное "умные указатели". Ведь это именно он со счетчиком.
Двачую, мой промах.
Я тОжЕ кРесТоБлядь, особенно по ++11 и ++14. И вот подумал я о такой хуйне - раз умные указатели такие дохуя умные и класные, лучше обычных, то какого хуя сделать unique_ptr to unique_ptr, становится таким убер-сложным? Да и к тому моей джуновской фантазии хватило на создание такого только в ++14 стандарте. Ну ка, мидлы и сеньоры, если вы конечно не пиздаболы, а ведь вы 99.9% пиздаболы, запилите мне создание аналога int только в терминах unique_ptr<unique_ptr<int> > причем только с помощью ++11? А чтобы пруфануть что я серьезный джун, а не выблядок из всяких там ШАГов, держите ++14 сниппет:
std::unique_ptr< std::unique_ptr<int> > nested = std::make_unique<std::unique_ptr<int> >(new int(5));
А в чём проблема-то, ёбана?
> auto nested = std::unique_ptr<std::unique_ptr<int>>( new std::unique_ptr<int>(new int(5))) ;
Пидоры просто забыли добавить в 11 стандарт std::make_unique
Ну так давай, сынок, напиши мне эквивалентный моему код без использования make_unique
>Добавлю только - что на область памяти может быть дохрена указателей откуда угодно
Поэтому умные люди на всяких cppcon советуют не пользоваться указателями и говорят про всякие value semantics.
https://ru.wikipedia.org/wiki/Факторизация_целых_чисел
>>556122
value semantics иногда приемлема и эффективна, но иногда и без reference semantics не обойтись(отношения между сущностями 1-N, N-M).
Не совсем так. Оверхеда нет только у unique_ptr с дефолтной стратегией удаления (это прописано в стандарте). Если ты делаешь вторым шаблонным аргументов кастомный deleter, то его копия будет храниться в каждом указателе, и размер увеличится по сравнению с raw-poiner.
Еще как нужен. Например, тебе нужно передать куда-то джва unique_ptr на объекты, которые ты конструируешь на месте. Без make_unique ты либо вынужден писать unique_ptr<T>(new T(std::forward<Args>(args)...)), что уебищно из-за отсутствия вывода параметров и при длинных T вообще не влезет в строку, либо передавать голые указатели, созданные через new, чтобы они неявно перобразовались. И вот тогда ты в один прекрасный момент соснешь из-за того, что второй конструктор выбросит исключение, и указатель на уже созданный первый объект потечет как твоя мамаша-шлюха. make_unique это фактически первый вариант, записанный коротко, так что >>556098 - уебок спизданул хуйню про какую-то сложность, ибо всегда можно написать три строчки со своим make_unique.
>хитро
>простейший для человека с зачатками обобщенного мышления пример
>хитро
Блядь, ну опять школьники протекли, каникулы штоле? Иди читни Саттера уже, хитро ему, пиздец. Тут взрослые дяди обсуждают серьезные проблемы, а не применение базовых синтаксических пряников уровня Праты.
Не, ну в бизнес-логике-то конечно, но под капотом у любых сложных архитектур это будет. Когда не просто объекты вызывают методы друг друга, а есть многоуровневые зависимости, некоторые из которых владеющие, а другие - нет. Когда полиморфная обработка коллекций нужна. Да даже банально когда ты хочешь быстродействие повысить, передавая 4 байта вместо пары десятков.
Там приватное наследование, а не композиция (например, в VC++ он пихает deleter в _Compressed_pair, который первый параметр так сжимает, если он пустой), так что если у тебя deleter не хранит состояние, то сработает empty base optimization и оверхеда таки не будет.
Только если ты уже писал на C-подобных языках.
Лучше всего использовать константные объекты, инициализирующиеся только в конструкторе.
>int make() {
>int i = new int;
>return i;
>}
OK, а удолить его как?
#include <iostream>
int@ make()
{
\tint@ i = new int;
\treturn i;
}
int main()
{
\tstd::ios::sync_with_stdio(false);
\tint* array = make();
\tarray[0] = 7;
\tstd::cout << array[0] << '\n';
\tstd::cin.get();
\treturn 0;
}
Как этот код читать? Используй пастбины
Именно delete, без квадратных скобок?
Держи супер код от makakacpp, я сегодня добрый и решил показать тебе немножко с++11 магии:
#include <iostream>
#include <memory>
class myCla {
public:
~myCla(){std::cout<<"hello RAII"<<std::endl;};
};
std::unique_ptr<myCla[]> ownerPointerCreator(size_t nElem) {
return std::unique_ptr<myCla[]>(new myCla[nElem]);
};
int main() {
/std::unique_ptr<myCla[]>/ auto uniquee = ownerPointerCreator(10); //creates unique_ptr to 10 elements which are automatically deleted
std::cout<<"ohoho"<<std::endl;
return 0;
};
>>556208
Не пизди, плс, раз такой дохуя образованный и начитанный, давай интересные идеи или вопросы как что-то сделать, только не начинай тут кидаться баззвордами. Или ты мамкин фантазер?
>return 0;
>};
Последний символ ; на последней строке лишний. В общем, вот твой код:
http://ideone.com/hmbmaE
А на 6 строчке последний символ ; не лишний?
#include <iostream>
using namespace std;
void main()
{
\tsetlocale(LC_CTYPE, "Russian");
\tfloat a, t, j, y, z, w;
\ta = -1; y = 0.4; t = 5e-5; j = 1;
\twhile (j <= 2)
\t{
\t\tz = sqrt(t a + y) + 4.0 exp((-2.0) j);
\t\tw = log(0.4 y) / (7.0 * a - z);
\t\tprintf("j = %5.2f\t", j);
\t\tprintf("d = %5.2f\t", z);
\t\tprintf("c = %5.2f\n", w);
\t\tj = j + 0.2;
\t}
}
Эта мразота выводит значения до j=1.80. Почему не до j=2.0? Почему программе вообще похуй, что я написал "<=", а не "<"? Можно, конечно, заменить 2 на какое-нибудь число в промежутке от 2 не включительно до 2.2, но мне кажется, что это неправильно. Или так и надо?
дружище, с такими вопросами ты будешь друзей своих подъебывать, я ставлю ; в конце любого выражения, скоупа и конца функции. Если ты считаешь что они лишние - может ебанешь сюда правила навроде питоновского pep8 как и где нужно ставить ; по канонам? Я лично не видел таких, поэтому руководствуюсь перестраховкой
Потому что числа с плавающей точкой не гарантируют тебе точность вычислений:
http://ideone.com/fXVzTU
http://ideone.com/peON7q
держи студент ответ на свой вопрос. И знай - если ты хочешь быть нормальным кодером а не говном, то никогда не итерируй циклы числами с плавающей точкой, потому что они никогда не представляются 2.0 в памяти, а примерное как-то 2.000000001. Я тебе наглядный пример там сделал, если нолик один уберешь, то уже 2 не пройдет.
>все та же makakacpp
7 вариант нужен.
Нет никакой методички, это все, что нам дали на лабе.
400 рублей на яндекс деньги, и напишу. 200 вперед. если интересно пиши на mame_privet@rambler.ru договоримся
Хорошо тогда. А то синтаксис-то я знаю как родной, домашнего опыта с крестами семь лет уже, но ничего полностью написать так и не осилил, потому что все и так уже есть.
Пользователь задает размер матрицы, а матрица должна заполняться рандомом. В конце вывод всех вариантов сразу.
А, ок.
[code lang="c++"]
#include <iostream>
void main()
{\t
\tint n, x, y, z;
\tfor (n = 1; n++)
\t\tfor (z = 1; z < n; z++)
\t\t\tfor (y = 1; y <= z; y++)
\t\t\t\tfor (x = 1; x <= y; x++)
\t\t\t\t\tif (pow(n,2) = pow(x,2) + pow(y,2) + pow(z,2))
\t\t\t\t\t\tstd::cout << "n = \n" << n << "x = \n" << x << "y = \n" << y << "z = \n" << z;
}
[/code]
Чяднт? Заранее спасибо.
Двачую. Надо еще всегда явно указывать шаблонные параметры, чтобы не дай б-г неправильно не вывелись. std::move <OcheDlinnyIdentifikator> (foo), крастотища-то какая! И заодно ДЛЯ ПЕРЕСТРАХОВКИ скобок побольше ставить, ну типа (a+(b*c)), а то вдруг приоритеты операторов поменяются.
>перестраховкой
Это у тебя недостаточно безопасно. Надо вот так:
[code lang="cpp"]
foo ();;;
//newline
//newline
[/code]
foo () может оказаться макросом и съесть семиколон, а у тебя еще один есть, охуенно же!
Короче. Ну и удобнее тем, что можно писать прямо в тексте в кавычках. endl нужен, когда у тебя тупо вывод значений переменных без этого текста.
РЕГУЛЯРНЫМИ ВЫРАЖЕНИЯМИ[\b]
[code lang="cpp"]
struct Yoba {
Yoba(std::string yba) : yba{ std::move(yba) } {}
private:
std::string yba;
};
[/code]
повысит ли оно производительность?
киданите норм литературы за std::move и всё связанное с подобным
Повысит в данном случае и вообще во всех, где в перемещаемом объекте не простые члены, а всяческие указатели и глубокие структуры.
Я сегодня читал, не до конца разобрался.
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
http://thbecker.net/articles/rvalue_references/section_01.html
Дрочую этова знатока.
>>556553
почитал эту жуть.
вот если на таком примере
[code lang="cpp"]
std::string str{ "mamka" };
Yoba yoba{ str }; // Yoba(std::string yba)
[/code]
то я правильно понимаю, что str скопируется во временный объект yba, который указан как аргумент, и уже внутренности yba (аргумент) переместятся в yba (член класса)?
Да, то есть у тебя будет одно полноценное копирование вместо двух. Но твоя цель - сделать вообще ноль, поэтому передавать yba надо по ссылке. А чтобы нельзя было передать аргументом вместо временного значения str, которая от перемещения испортится, ссылку надо сделать && (то есть rvalue).
Ясно.
Она присутствует уже.
[code]class myclass
{
private:
...
public:
const matrix &operator()() const
{
const matrix &t;
return t;
}
};[/code]
Пишут, что так делать нельзя, хотя, если мне не изменяет память, Visual Studio такой код компилировала, а сейчас сижу под линухом и он работать не хочет. Получается, Visual Studio удаляла объект не сразу, а после того, как он отработает в основной программе. gcc такую хуйню не пропускает и удаляет объект сразу после завершения функции. Два вопроса: 1) Чому VS компилировала, идя в разрез со стандартом (насколько я понял)? 2) Как мне теперь быть? есть ли ещё какие-то варианты?
http://alenacpp.blogspot.ru/2008/01/const.html
Вот здесь эта ваша Алёна пишет, что если добавить const, то всё должно работать.
Сейчас попробовал с int. Если возвращать const int &, то всё действительно работает, но ничего не работает, если я возвращаю const myclass &. Видимо, это связано с тем, что после завершения функции вызывается деструктор, а для int ничего такого нет. Почему так странно? Ведь было бы логичнее, если бы деструктор вызывался после того, как объект отработает в вызвавшем его выражении.
Ну смотри, есть такой код:
[code]mycalss A;
cout << A(1);[/code]
По моей задумке A(1) должен был иметь тип const myclass& и создаваться в функции:
[code]const myclass &operator()(int n)
{
return { ... };
}[/code]
То есть порядок действий такой:
1) список инициализации вызывает специальный конструктор;
2) создаётся объект;
3) константная ссылка на него передаётся в основную программу к cout;
4) cout работает с A(1);
5) вызывается деструктор для A(1).
Но в этом коде всё идёт по пизде, так как последовательность действий становится такой:
1) список инициализации вызывает специальный конструктор;
2) создаётся объект;
3) ссылка на него передаётся в основную программу к cout;
4) вызывается деструктор для только что созданного объекта;
5) ломается cout, который пытается работать с уже удалённым объектом.
Так вот с const int & всё работает (я предположил, что это как-то связано с деструктором), а с const myclass& нет.
Причём Visual Studio почему-то нормально компилировала такой код, то есть порядок действий соответствовал тому, что я хотел. В gcc какой-то пиздец.
Я могу, но я спать
Ты вообще все перепутал. Из функции нельзя возвращать ссылку на что-либо созданное внутри, это сразу UB, независимо от того, чему там ты снаружи присвоишь возвращенное. Известно, что конкретно VS такое дело прощает, но энивей это плохо, нестабильно и запрещено стандартом.
У Лены и Саттера речь шла не про это, а про то, чтобы присвоить возвращаемое функцией нормальное значение которое будет rvalue, временным не нормальной переменной, а ссылке. Обычно ссылка смотрит на какую-то другую переменную, а тут она как бы становится единственной точкой доступа к этому возвращенному значению. Поэтому и разрешены только const ссылки и && на момент того поста rvalue ссылок еще не было, но теперь с ними тоже можно так делать, ибо только такие ссылки могут указывать на rvalue-объект.
Я же кида ссылку.
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
Пункт Detecting temporary objects with rvalue references
&& references не обязаны быть константными, охуенно же.
>Из функции нельзя возвращать ссылку на что-либо созданное внутри, это сразу UB, независимо от того, чему там ты снаружи присвоишь возвращенное.
Хорошо, я понял это.
>У Лены и Саттера речь шла не про это
Да, осознал.
Тогда вопрос, что использовать, чтобы как-то смоделировать нужное мне поведение (>>556650), чтобы cout смог отработать с объектом до удаления? Есть какие-нибудь пути обхода, кроме операции new в функции?
Нет, однозначно. Когда ты вышел из функции, ее стековый фрейм уже не существует, все сдвинулось на внешнюю функцию с ее фреймом. Теоретически ты можешь попробовать залезть в старый фрейм, но он может как оставаться прежним например, VS не удаляет ничего, а просто сдвигает стековый регистр на предыдущий фрейм, но никаких гарантий нет. В самом лучшем случае твой объект по ссылке будет существовать до первого же вызова любой другой функции или вычисления выражения, потому что в этих случаях используется стек, и то, что было на месте старого фрейма, будет реквизировано для этих вычислений. А на практике ОС может защищать свободную часть стека от вот таких посягательств, и ты словишь SEH-exception. Ну и разумеется при выходе из функции, даже если ты возвращаешь ссылку, для самого локального объекта будет вызван деструктор, и этого никак не избежать. Так что если деструктор нетривиальный, и действительно что-то уничтожает, то ты тоже соснешь. В общем, лучше не пытайся даже.
Алёна тупая пизда, о чём я писал неоднократно, но ОП этого треда меня игнорировал. Добавь конст и верни ссылку на вектор, а затем счастливо отстрелить себе обе ноги по самую глотку.
А зачем вообще это надо-то? Если ты не выделяешь для него место динамически из-за байтоебства, и из-за байтоебства же не хочешь лишний раз копировать объект в возвращаемое значение, то учти, что сейчас во всех компиляторах работает named return value optimization, т.е. то, что ты возвращаешь, никуда не скопируется, а "типа локальная" переменная уже будет создана на месте возвращаемого значения, хотя для тебя это будет выглядеть как обычный return. Так что возвращай по значению и не выебывайся.
А Саттер тоже тупая пизда? Это ведь дословный перевод его статьи из GotW, а статья та ссылается на стандарт. Вообще, меня умиляет твоя ненависть к Лене, тому що ты же вместо адекватной критики норовишь облить говном все, что связано с ее именем, даже если это святая правда, которую она сагрегировала с других сайтов.
>будет существовать до первого же вызова любой другой функции
У меня как раз после этой функции вызывается operator<<, поэтому ничего не остаётся.
>ты словишь SEH-exception
Словил.
В общем, это печально. Видимо, придётся менять подход к классу, чтобы хоть как-то можно было реализовать такое поведение, но из-за этого всё раздуется в разы.
Может быть, тогда подскажешь, как можно реализовать класс матриц, чтобы можно было писать такие конструкции:
[code]matrix A(4, 4); //random 4x4
cout << A(1);
A(1) = A(2) + A(3);
A = A * A[1];
cout << A;[/code]
Проблема не в том, что нужно в функциях писать, а в том, какой подход использовать в целом. Я перебрал много вариантов и остановился на том, с которым сейчас ебусь, ибо VS меня даже не поругала. Я хотел сделать один класс matrix, который бы позволял получить доступ к строкам и столбцам через operator() и operator[] соответственно, и при этом сами стобцы/строки были бы тоже типа matrix и, естественно, были бы не просто копиями, а действительно имели доступ к исходной матрице. В общем, всё было хорошо, пока не выяснилось, что так писать нельзя, то есть я не могу создавать объект в функции. Следовательно мне нужно хранить какие-то объекты с самого начала (хранить объекты matrix, отвечающие за строки и столбцы, не выйдет). Видимо, придётся делать класс-прослойку, объекты которого будут отвечать за строки и столбцы и хранится в исходном объекте класса matrix. Как бы сделал ты, анон?
Я не понимаю твою мотивацию все равно. Хуй знает, чего ты там наворотил, какие-то матрицы из матриц, вообще охуеть. () и [] для строк и столбцов это просто пушка, я еще не видел настолько дикой реализации обращения к элементам.
Вот как бы решил твою задачу нормальный человек. Делаешь класс матриц, неважно, как внутри там все хранится обычно это либо vector <vector <тип элемента>>, либо тип элемента [] []. Делаешь operator [], который возвращает ссылку на строку в виде соответственно vector <твой тип> или твой тип *. Для обоих уже определены свои operator [], поэтому для доступа к конкретному элементу ты просто будешь писать matrix [j], что эквивалентно (matrix ) [j]. При таком раскладе вообще не создается никаких временных объектов, ты оперируешь только ссылками. Доступ к столбцу как к единому целому ты не получишь можно поменять местами столбцы и строки, но тогда не получишь доступ к строке, ну ты понел, но одновременный доступ к столбцам и строкам нужен очень редко, да и оптимально это не сделаешь, потому что по любому что-то из них будет непоследовательно в памяти находиться. Поэтому на это просто забивают, а если очень надо, то выбирают столбец поэлементно в цикле или типа того. Для этого можно сделать метод, да, но называть его operator () это полный пиздец, потому что когда я вижу matrix (1), я ожидаю, что matrix это функтор, а () - его вызов, а твоя семантика будет полной неожиданностью.
>А Саттер тоже тупая пизда?
А почему бы и нет. Уж кого-кого, а а этого персонажа ненавидят просто в промышленных масштабах.
Но он, полагаю, в отличие от Алёны хотя бы void main() { exit(0); } не пишет (ну,я надеюсь на это).
>я еще не видел настолько дикой реализации обращения к элементам
У меня не к элементам обращение, а полностью к строке/столбцу. Мне захотелось сделать именно так, ибо это интуитивно (A(1) -- строка, A[1] -- столбец), ведь в алгебре столбцы записываются в квадратных скобках, а строки -- в круглых. В любом случае это не так важно сейчас.
>Доступ к столбцу как к единому целому ты не получишь
Собственно, поэтому и решил делать по-другому, ибо мне нужны оба доступа. Сначала, конечно, делал так, как ты и посоветовал, но, столкнувшись с этой проблемой, решил всё переписать, и, как оказалось, неудачно. Теперь, видимо, придётся делать какой-то класс-прослойку, чтобы хранить указатели не только на строки, но и на столбцы. И у меня вроде бы уже появилась идея, как это сделать. Через vector вряд ли получится такое провернуть.
Можно, но тогда не получится писать так:
[code]A(1) = A(2);[/code]
, чтобы менялась матрица A.
>>556734
Как я понял, proxy это естественный подход. См. http://www.boost.org/doc/libs/1_59_0/libs/numeric/ublas/doc/ , в частности, http://www.boost.org/doc/libs/1_59_0/libs/numeric/ublas/doc/matrix_proxy.html
>Роберт Лафоре - Объектно-ориентированное программирование в C++
Правда устарело? У меня книжка нового издания, не жалуюсь. Брата вообще нет.
Cам ее учил 4 года назад. Но могу заверить, все книги по крестам до 2012 года - устаревшие.
Во-первых если ты делаешь матрицу для линала/численных методов - делай на одномерном массиве, в который упаковывается матрица(например, по строкам). Vector - это оверхед ради "динамичности" матрицы(возможности менять размерности после создания) и "невыровненности"(разные длины строк могут быть). С массивом еще проще обращаться к столбцам - просто прибавляешь к указателю на элемент длину строки*кол-во столбцов на которые нужно сместиться.
Можно сделать отдельный доступ к строкам и столбцам через прокси-классы. В них будет ссылка на матрицу и на номер строки/столбца+вычисления с указателями.
И вообще нахуя ты делаешь свою матрицу, когда есть годные реализации с нужными алгоритмами? Для обучения/понимания внутреннего устройства? Лучше наверно чужие качественные исходники почитать и поучиться, чем свой говновелик делать.
>void main ()
Петрович, заебал. Чего тебе этот косяк с main-то так въелся? Уже десять лет прошло, она тогда вообще студентотой была. Вспомни свой код на втором курсе, блджад. То, что она вместо вмкшных говноучебников Вылитка читала в свое время Саттера - это оче похвально, ибо переварить гигантский объем best C++ practices, которые часто еще и противоречат друг другу, гораздо сложнее, чем просто делать, как в учебнике сказали. Ну не разобралась тогда с void этим, бывает, хуле. Зато МЫШЛЕНИЕ присутствует, блджад, "а можно ли сделать не int main (), а как-то еще?". Для тянки это вообще нонсенс практически, а ты тут пиздишь что-то про тупопездность.
Не векторе будет лишь небольшой оверхед из-за лишнего уровня косвенности при обращении, ну и выделяться будет медленнее на куче. Если матрицы фиксированного размера, а тебя прямо прет сделать быстро, то используй std::array без оверхеда, все равно удобнее массивов же. Но для больших матриц стек может засраться от такого использования.
Какое нахуй мышление, поехавший? Я сам новичок, в каком-то смысле первокурсник, если хочешь. И первое, что я сделал, это задал вопрос: почему main int? На что мне последовал вполне чётко понятный и определённый ответ: это стандарт языка, причём стандарт языка C.
И функция должна возвращать код успешного выполнения или код ошибки на который, тем не менее, всем похуй. И это правильный вопрос, который возникает: как делать правильно, если ты новичок.
Вообще, новичку надо читать Страуструпа и только Страуструпа. Он своим подходом сразу отсеивает тупых, в т.ч. тупых пёзд. А все эти ваши Лафоре, Алёны и прочие только мозг разжижают. Ну нельзя же из пустой биологической матрицы сразу говно делать, надо людям сначала мозги вправить, а потом сами пусть решают, Саттера им читать или Александреску.
>будет лишь небольшой оверхед
оверхед вроде небольшой, но может сыграть существенную роль при большом количестве вычислений на матрицах(что типично для алгоритмов линала-вычмата)
>ну и выделяться будет медленнее на куче.
Массив я тоже предлагаю выделять на куче - но выделяться он будет только при конструировании матрицы. Выигрыш будет за счёт снижения "уровня косвенности", более плотной упаковки данных в памяти(не забываем про процессорный кэш - это существенный аргумент), "лишних" указателей и "неиспользованного пространства" в конце вектора(впрочем, его можно избежать если зафиксировать capacity).
Оверхед будет большой из-за кэш промахов.
Лично я читал кернигана и Ричи , потом дизайн и эволюцию , потом саттера. Толстая книга страустпупа почти бесполезна потому что не объясняет а хуьи так костыльно
Ну можно с Кернигана и Ритчи начать, а потом например как ты. Только вместо Саттера я бы лучше Майерса навернул (это и есть в моих планах, когда слезу с дивана).
>существенную роль
Неа. Смотри, у тебя есть оче большая матрица, но ты же не для каждого элемента будешь заново спрашивать указатель на raw-data, а потом уже на сам элемент. Вместо [][] каждый раз ты можешь запомнить .data () в начале операции над матрицей, а потом уже работать с содержимым вектора без косвенности, как с голым массивом. Преимуществом будет то, что тебе не придется заниматься менеджингом всех этих элементов, рассчитывать размеры, сдвиги и вот это все. А пока ты не меняешь размер матрицы, на каждую матричную операцию добавится ровно одно лишнее разыменование, которое будет ничтожно влиять по сравнению с самими операциями над элементами.
>выделяться он будет только при конструировании матрицы
А вектор тоже тебя никто не заставляет выделять заново после начала работы. Если ты не меняешь его размеры, ты ничего платить не будешь, но, в отличие от массива, ты таки можешь поменять размеры, что есть хорошо.
>не забываем про процессорный кэш - это существенный аргумент
А что кэш? Как массив, так и вектор хранятся последовательно, это стандартном регламентировано.
>"лишних" указателей
На VC++ Win32 вектор занимает 12 байт. 4 байта указателя на raw-массив, 4 на size, 4 на capacity. Даже для небольших матриц 8 лишних байт это оче небольшой оверхед, а вот скорость увеличится существенно, если ты часто обращаешься к размеру массива. Для голого тебе придется юзать distance или типа того, потому что в compile-time ты знаешь размер массива до первой его передачи в функцию или преобразования в указатель. Дальше только адрес начала и все. А с вектором ты считываешь size за одно обращение к памяти.
>неиспользованного пространства
shrink_to_fit () после каждого изменения размера. Опять же, если ты не меняешь размер, то ты не платишь за это.
В общем, я считаю, что конкретно вектор в отличие от многих других фич не стоит менять на массив даже на всратых встроенных системах, потому что оверхед ничтожен по сравнению с преимуществами, ну, в большинстве случаев.
std::vector
В вопросе возвращаемых значений есть много тонкостей. К примеру, в main ты не обязан писать return 0, он подразумевается по умолчанию, и это регламентировано стандартом C++. Потом, в стандарте Pure C правила другие, там вообще емнип допустим void main (), и просто main (), и даже Аллах. Где-то подобные вещи помогают сэкономить, потому что без return не будет лишней операции по помещению ненужного тебе возвращаемого значения в стек. То, что C++ запретил это - дело десятое, до стандартизации в плане совместимости с C был бардак, каждый компилятор дрочил как хотел. Поэтому я не вижу ничего криминального в том, что Лена немного попутала инфу, пытаясь разобраться в том, что в каком стандарте допустимо.
>причём стандарт языка C
Да ну? Открываем K&R, страница 84:
>Если тип возвращаемого значения опущен, по умолчанию подразумевается int. ... Более того, после return вовсе не обязано стоять выражение, в этом случае в вызывающую функцию ничего не передается.
Подозреваю, что ты первокурсник какой-то шараги, раз преподы K&R не осилили. А ты, в силу эффекта Даннинга-Крюгера еще гонишь на Лену, которая няша-умняша и вообще успеха в Редмонде своем добилась давно.
А ты обоснуй, обоснуй. Возражай по существу давай, кукарекать-то МНЕ НА СЕМЕНАРЕ СКАЗАЛИ ЧТО ВЕКТОР МЕДЛЕННАЙ каждый может. Чай 2015 год на дворе, а не 1989.
fix: ++ проебал при написании
>>На что мне последовал вполне чётко понятный и определённый ответ: это стандарт языка, причём стандарт языка C.
>А ты, в силу эффекта Даннинга-Крюгера
Молчать! Сколько истребителей, сука.
>Стандарт C++ требует, чтобы функция main() возвращала тип int. Программа, которая имеет другой тип возвращаемого значения функции main(), не соответствует стандарту C++.
>Стандарт не говорит о том, что на самом деле означает возвращаемое значение функции main(). Традиционно оно интерпретируется как код возврата программы. Стандарт гарантирует, что возвращение 0 из функции main() показывает, что программа была завершена успешно.
>Завершение программы на C++ с ошибкой традиционно обозначается путём возврата ненулевого значения.
А я напомню, что Алёна называет себя C++ программистом, не C программистом.
http://ideone.com/T42RP5
>>556884
Не понятно, что из этого следует? Что ты знаешь С++ лучше Алены? Вряд ли. Полностью С++ со всеми камнями не знает никто, особенно подобную хуйню, которая практикующему программисту и не нужна.
Иии? В твоем примере, начиная с размера 200 первый вариант обгоняет второй по скорости.
>я нет
Вооот. Так что позволь уж программистам решать, что должно находиться в шапке и помогать вам, неучам, постичь тайные знания.
А, так ты ты у нас программист с void main()? Ну так иди нахер со своей шапкой тогда.
А я в этом треде вообще ради байтоёбов сижу.
Ему вектор там нужен, а не пилить указатели для массивов.
Хотя вообще по дефолту указатели не особо нужны. Не знаю, что у тебя там за дефолт такой. По-моему по-дефолту всякие стандартные структуры данных, а указатели - для создания новых структур данных, и там дефолта никакого нет.
>Нет, из этого следует, что её нужно убрать из шапки этого треда.
С хуя ли? Нормальный блог (во всяком случае был до эмиграции). А ошибки все делают. Ну, кроме анонимных школьников.
Но мы же с тобой говорили о сравнении работы голых массивов и второго варианта из твоего примера, а не второго варианта с первым. Видимо, не поняли друг друга просто.
Ты не понял одной вещи - матрица, упакованная в одномерный массив это не двумерный массив(аналог vector<vector<typename>>). Размерности ты хранишь в отдельных переменных(как в векторе). В нём проще пробегаться по столбцам, к примеру(просто операции с индексами индекс i-го элемента j-го столбца =j+i*n, n - количество столбцов. Чтоб перейти к следующему элементу достаточно прибавить n к указателю на элемент. А чтоб пробежаться по столбцам вложенного вектора придётся сначала "разыменовать" первый вектор. И еще массивы вложенных векторов не обязаны лежать рядом в памяти - это не один сплошной вектор. Сплошняком лежат только структуры вектора, про которые ты сказал, а их массивы выделены на куче по отдельности.
Я вел речь о сравнении обычных C-like массивов в духе typename [][size] с вектором размера size*size. То, что ты называешь двумерным массивом, называется "неровный массив". Их, как и векторы векторов, я не предлагал использовать. Перечитай внимательнее мой пост, там сравнивается только голый одномерный массив по сути с собой же, но с оберткой в виде одномерного вектора. Я говорил о том, что эта обертка дает удобство на этапе создания с крайне малыми накладными расходами, если ты при обращении первым делом достаешь data () и работаешь дальше с raw-данными.
И да, пробег по столбцам в обоих этих случаях все равно будет медленный как раз из-за того, что ты ступаешь по n элементов, и кэшированная секция быстро заканчивается.
ОК, согласен. В случае использования простого вектора разница минимальна и не принципиальна при написании своего класса матрицы, имхо. С одномерным массивом будет чуть больше кода, но зато не надо заморачиваться с .data().
Вангую там где-то закопан труп страуса. Кто-нибудь попробуйте скомпилировать с -o3 и запустить.
Как написать кроссплатформенное приложение? Например в плюсах разнятся команды между виндой и линуксами с такими командами как system('cls') или system('pause')
Как написать один код и скомпилировать его для двух систем? Ну для винды скомпиляю под вижуалом, конечно же - просто не хочу исправлять вот некоторые команды, например те что упомняул выше.
Никак. Консоль implementation defined, стандарт языка на неё влиять вообще не вправе.
В том-то и проблема, что новичок распознать их не сможет, а до комментариев, где её хуесосят её же френды, добраться не осилит.
ну вот смотри
Кодовая база гугл хрома или файрфокса общая для всех платформ. Как они это сделали? Таким образом, изучение сорцов поможет ответить тебе на твои вопросы.
Альтернативный вариант - системы контроля версий (git, svn). Они же тоже работают под всеми платформами, но гуевые приложения у них стороние и сделаны под каждую платформу.
Обходиться без system() в основном коде. system('pause') -> cin.get(), system('cls') -> написать платформо-зависимую функцию отдельно под windows и linux и включить в код через #ifdef(в зависимости от #define WINDOWS или #define Linux используются разные варианты функции).
Либо использовать левую, не входящую в стандартную либу консоль. Поискал - годных вариантов вроде нет(встретил какой-то ncurses - под POSIX со старым портом под win).
Использовать то, что гарантирует стандарт, без всяких system (). Когда ты подключаешь кроссплатформенную библиотеку, то либо она является надстройкой над стандартом, либо при компиляции смотрит версию системы и в зависимости от нее выбирает одну из функций, которые работают схожим образом на разных платформах.
Для линуха напишу свой код (кстати как в с++ почистить консоль линукса? system("clear") - не работает). А для спермы просто напишу в этой функции строчку system("cls"). и Всё. Не придется бегать по всему коду и исправлять по одной строчке.
Так можно сделать? Какие подводные камни?
Пиздец. Вопрос какого-то 9-классника, которому впервые дали в руки язык программирования.
Все платформозависимое выделяешь в отдельную библиотеку. Пишешь библиотеки под все нужные системы, компилируешь с нужными библиотеками. Ну или ищешь готовое, например если тебе с консолькой пердолиться то можно ncurses подцепить.
system в винде это типа запустить команду в шелле?
Чому не пашет.
#include <iostream>
using namespace std;
void chistichisti
{
for(int i = 0; i < 100; i++)
printf("\n");
}
int main()
{
void chistichisti;
cout << "Hello World \n";
return 0;
}
12 строчка - полная хуйня. Функции не так вызываются, а вот как - chistichisti();
Хорошо, * не каждый новичок.
Исправил. не помогло.
#include <iostream>
using namespace std;
void chistichisti
{
for(int i = 0; i < 100; i++)
cout << "\n";
}
int main()
{
chistichisti();
cout << "Hello World \n";
return 0;
}
Ошибка:
1.cpp:4:6: error: variable or field ‘chistichisti’ declared void
void chistichisti
^
1.cpp:5:1: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
{
^
1.cpp:6:1: error: expected primary-expression before ‘for’
for(int i = 0; i < 100; i++)
^
1.cpp:6:1: error: expected ‘}’ before ‘for’
1.cpp:6:16: error: ‘i’ does not name a type
for(int i = 0; i < 100; i++)
^
1.cpp:6:25: error: ‘i’ does not name a type
for(int i = 0; i < 100; i++)
^
1.cpp:8:1: error: expected declaration before ‘}’ token
}
^
Исправил. не помогло.
#include <iostream>
using namespace std;
void chistichisti
{
for(int i = 0; i < 100; i++)
cout << "\n";
}
int main()
{
chistichisti();
cout << "Hello World \n";
return 0;
}
Ошибка:
1.cpp:4:6: error: variable or field ‘chistichisti’ declared void
void chistichisti
^
1.cpp:5:1: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
{
^
1.cpp:6:1: error: expected primary-expression before ‘for’
for(int i = 0; i < 100; i++)
^
1.cpp:6:1: error: expected ‘}’ before ‘for’
1.cpp:6:16: error: ‘i’ does not name a type
for(int i = 0; i < 100; i++)
^
1.cpp:6:25: error: ‘i’ does not name a type
for(int i = 0; i < 100; i++)
^
1.cpp:8:1: error: expected declaration before ‘}’ token
}
^
>Warning C28182 Dereferencing NULL pointer. 'natural_numbers' contains the same NULL value as 'Temp_value_#1999' did. main.cpp 43
>Warning C6386 Buffer overrun while writing to 'natural_numbers': the writable size is 'unsigned int' bytes, but '2' bytes might be written. main.cpp 44
Совершенно точно никакой херни нет, разметка памяти. Что ей нужно-то?
>bool natural_numbers = new bool[100]();
>//if (!natural_numbers) return;
>natural_numbers[0] = true; //C28182
>natural_numbers[1] = true; //C6386
delete[] natural_numbers;
Если раскомментить if, то C28182 исчезнет. Если убрать ()
>bool natural_numbers = new bool[100]();
то оба предупреждения отвалятся, но мне calloc нужен!
fix:
Вижуал Студия подзаебала сыпать вот этими двумя предупреждениями при анализе кода:
>Warning C28182 Dereferencing NULL pointer. 'natural_numbers' contains the same NULL value as 'Temp_value_#1999' did. main.cpp 43
>Warning C6386 Buffer overrun while writing to 'natural_numbers': the writable size is 'unsigned int' bytes, but '2' bytes might be written. main.cpp 44
Совершенно точно никакой херни нет, разметка памяти. Что ей нужно-то?
>bool* natural_numbers = new bool[100]();
>//if (!natural_numbers) return 1;
>natural_numbers[0] = true; //C28182
>natural_numbers[1] = true; //C6386
delete[] natural_numbers;
Если раскомментить if, то C28182 исчезнет. Если убрать ()
>bool@ natural_numbers = new bool[100]();
то оба предупреждения отвалятся, но мне calloc нужен!
Мне кажется, это значит, что твой код неправильный
conio.h тоже не найден
gcc
Ну так если ты закомментируешь if, то получается, что в C28182 может случиться именно то, что там написано, потому что new не всегда успешно выделяет память
throw куда-нибудь
Вероятно то же самое - компилятор указывает тебе на то, что если этот new bool[100]() зафейлится, и natural_numbers будет указывать на nullptr, то строчка с C6386 - это undefined behaviour.
ещё раз:
>bool* natural_numbers = new bool[100]();
>if (!natural_numbers) return 1;
>natural_numbers[0] = true;
>natural_numbers[1] = true; //C6386
>delete[] natural_numbers;
И это при раскомментированном ифе:
>Warning C6386 Buffer overrun while writing to 'natural_numbers': the writable size is 'unsigned int' bytes, but '2' bytes might be written. main.cpp 44
Я не знаю, почему так. Может баг компилятора.
хочу ололо-меню сделать и не пашет:
int main(){
int punkt;
punkt=1;
if(punkt=5) {exit(0);}
}
#include <iostream>
using namespace std;
int main()
{
int punkt;
punkt=1;
cin >> punkt;
if(punkt=5) {exit(0);}
return 0;
}
---
2.cpp: In function ‘int main()’:
2.cpp:9:20: error: ‘exit’ was not declared in this scope
if(punkt=5) {exit(0);}
^
2.cpp: At global scope:
2.cpp:11:1: error: expected unqualified-id before ‘return’
return 0;
^
2.cpp:13:1: error: expected declaration before ‘}’ token
}
^
user@computer:~/Safety$ g++ 2.cpp
2.cpp: In function ‘int main()’:
2.cpp:9:20: error: ‘exit’ was not declared in this scope
if(punkt=5) {exit(0);}
^
#include <iostream>
using namespace std;
int main()
{
int punkt;
punkt=1;
cin >> punkt;
if(punkt=5) {exit(0);}
return 0;
}
---
2.cpp: In function ‘int main()’:
2.cpp:9:20: error: ‘exit’ was not declared in this scope
if(punkt=5) {exit(0);}
^
2.cpp: At global scope:
2.cpp:11:1: error: expected unqualified-id before ‘return’
return 0;
^
2.cpp:13:1: error: expected declaration before ‘}’ token
}
^
user@computer:~/Safety$ g++ 2.cpp
2.cpp: In function ‘int main()’:
2.cpp:9:20: error: ‘exit’ was not declared in this scope
if(punkt=5) {exit(0);}
^
О, ошибок стало меньше:
2.cpp: In function ‘int main()’:
2.cpp:9:21: error: ‘exit’ was not declared in this scope
if(punkt==5) {exit(0);}
^
Ублюдок, мать твою, а ну иди сюда, говно собачье, а ну решил ко мне лезть, ты... засранец вонючий, мать твою. А?! ну иди сюда, попробуй меня трахнуть, я тебя сам трахну ублюдок, анонист чертов, будь ты проклят, иди идиот, трахать тебя за свою семью, говно собачье, жлоб вонючий, дерьмо, сука, падла, иди сюда мерзавец, негодяй, гад, иди сюда ты говно, жопа!
exit () - выход со сверткой стека и вызовом пользовательских обработчиков непредвиденной ситуации.
quick_exit () - то же самое, но без свертки стека.
abort () - обработчики тоже не вызовутся.
Еще можно вызвать terminate (), это самый жесткий способ, мгновенное нештатное завершение. Оно же вызовется, если ты нашалишь в деструкторах или обработчиках при нормальном выходе.
>О, ошибок стало меньше
"Какая каша, думал Антон. Машины, оставленные негуманоидами. Гуманоиды, потерявшие человеческий облик, отчаянно старающиеся разобраться в этих машинах. Ведь они, несомненно, пытаются в них разобраться. Наверное, для них это единственное спасение… И у них, конечно, ничего не выходит…"
Т.е за сам opengl ничего не нужно.
А вот за библиотеки, которые окна рисуют , типа freeglut.
Я не ленивый, просто в нете слишком много инфы и она на английском - долго переваривать буду. и везде срач начинается аля sdl vs freeglut.
Пока ничего серьёзного на opengl делать не собираюсь - просто поиграться. Но на перспективу задумался.
В общем , что думаете (ну или ссылок накиньте, если. Есть)
Дополню:
Я знаю , что glut и sdl нужны для создания окна + sdl имеет плюшечки всякие типа звука, да?
Но если графику всё равно рисует сам opengl, то зачем такие дикие споры разводят по этому поводу?
Если нужны только окно и ввод - используй glfw, freeglut. Если звук, вывод текста и прочие плюшки - sdl, sfml. Еще больше плюшек, но не тяжеловесный движок - libcinder, openframeworks.
Я так понимаю, элементы не могут повторяться, то есть не могут в этих m элементах попасться пятый и еще раз пятый, так?
Берешь пикрелейтед [https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful ], генерируешь случайные числа
сначала от 0 до n-1, потом от 0 до n-2 и так далее. Причем на каждом шаге кроме нулевого мапишь числа так, чтобы в те номера, которые уже взяты не попасть (я надеюсь, ты справишься придумать, как это сделать). Если не справишься, то просто генерируй числа от 0 до n-1, а если такое уже есть, то генерируй заного, пока не будет так, что такого числа еще нет.
А вот эта задачка интересная. Сам с такой сталкивался. Самое простое решение - рандомишь и запоминаешь какие значения были, если повторение - повторно рандомишь пока не получишь уникальный номер.
А если по серьёзному подходить(с алгоритмами от серьёзных дядек и оценками сложности) - то
http://stackoverflow.com/questions/1608181/unique-random-numbers-in-an-integer-array-in-the-c-programming-language
55 советов зашли гораздо легче, вот последнюю его книгу вообще читать не могу, просто глаза слипаются.
ЧЯДНТ? Или у всех так?
https://mega.nz/#!LNwRCQLR!p0Cv6iL31KoXbktO-rBU-8xcpcPizSTef03LQ0DdnbU - Overview of new C++0x - название говорит, что книга чутка старая - когда 11-ый стандарт еще был 0x.
А вот еще на всякий случай выложу тут Effective Modern C++, который самый последний
https://mega.nz/#!7YQiFZxZ!cYbVseFxjaQBbr91YbDM-AauVtQIpKNhQpzP1m5L2zY
У меня он есть. Но мало ли, может кому пригодится.
Как-то он тяжело читается, вот с прошлыми не сравнить. Я не тупой, но мне банально скучно иногда и я не пойму зачем всяким мелочам столько внимания, когда реально насущные вопросы зачастую просто обходятся стороной.
Что-то правда я оттуда скачать нихуя не могу.
Требует установщик поставить, а там даже моей оси нет.
Нажми скачать через браузер
Я ебусь
на 10 ессесно
Почему вы юзаете какой-то mega.nz, а не google disk или dropbox? Он старые браузеры нахуй шлёт, а я фанат Opera 12, буду с ней до конца.
>из массива размерности n элементов случайно выбрать m элементов
>простой шаффл не катит
>скидывает простой шаффл 2 часа спустя
void f(std::thread t);
f(std::move(t));
Чем это отличается от простой передачи по ссылке.
>делай на одномерном массиве
Хорошая идея, уже практически реализовал все функции, спасибо.
>И вообще нахуя ты делаешь свою матрицу
Для закрепления базовых навыков. Хочу немного попердолиться с классами, чтобы быстро ориентироваться, что можно писать, а что нет. В общем, для усвоения материала, ибо я нуфаг. В будущем думаю переписать код на шаблоны. Только я их пока не знаю и, видимо, меня ждут новые подводные камни, поэтому код мне придётся переписывать не раз.
>Лучше наверно чужие качественные исходники почитать
А как они вообще ищутся? И как определить, годные они или нет?
Аноны, два насущных вопроса:
1) Как выделить память для массива объектов без конструктора по умолчанию?
[code]myclass *pc = new myclass[5];[/code]
Конструктора по умолчанию нет, ибо в классе находятся константы, которые должны правильно инициализироваться. Если я один раз их инициализирую, то поменять это уже нельзя будет. Можно ли как-то сначала выделить память, а потом вызвать конструктор? Что-нибудь с перегрузкой new придумать?
2) Имеет ли смысл делать два объявления функции, которые отличаются только const?
[code]const myclass &myfunc() const;
myclass &myfunc();[/code]
Реализации у них совпадают. Где-то видел такую тему, в каком-то коде, может быть. В чём смысл так писать?
Ну годнота - это STL, Boost, к примеру. Ищутся поисковиком, в твоём случае я набрал linear algebra library/C++ matrix - выдало stackoverflow с рекомендациями(к примеру либу Eigen, еще выдало GNU scientific library, Boost - но там нет линейной алгебры, только матрицы с базовыми операциями и.т.д.). В большинстве подобных либ исходники открыты, но есть закрытые и даже платные.
1.) Память выделяется до вызова конструктора. Создай пустой конструктор по умолчанию и инициализируй объекты позже(например, запили метод Init()).
А константы у тебя в каком смысле? Постоянны после создания объекта и разные для каждого экземпляра? Тогда это не C++ const(они должны быть известны во время компиляции), насколько я знаю - делай без const.
2) 2 варианта функции нет смысла делать, надо выбрать какую-то из них. Имеет смысл пердолиться с const, но далеко не всегда, некоторые авторитеты считают, что почти никогда. Для новичка - лишний геморрой. Читай про const-семантику - компилятор проверяет, чтобы ты с const-переменными не работал не-const методами.
GNU scientific library штука годная (помню, единственное, что нормально работало в C++ Builder 6), но это чистая сишка, соответственно это больше о интерфейсе со всякими недоязыками.
Boost ublas - говнище.
Мне нравится клон матлаба armadillo, но сейчас у тупо беру комбайн под названием opencv и не парюсь.
Для быстроты нужно то, что поддерживает ленивые вычисления. Eigen, вроде, работает норм.
Ленивые вычисления нужны, но далеко не всегда. Я бы сказал, для быстроты(в случае числодробилок) нужно то, что эффективно использует всякие расширения процессора вроде SSE, AVX и параллелится на GPU(OpenCL/CUDA). Хотя OpenMP-реализации вычислительных алгоритмов тоже покатят как компромиссный вариант, особенно если ядер штуки 4 хотя бы.
Мне может понадобится в проектике, да и побаловаться не против.
Это ортогональные вещи. Ленивость (а также сокращение подвыражений, выделение multiply-add операций и т. п.) позволяет эффективнее считать в том числе и на GPU.
Накатил CTP Update1 для Visual Studio Community 2015, всё так же. Безысходность.
Можно пример применения ленивых вычислений в линейной алгебре, и того как они ускоряют расчёт? Генерация матриц на лету? Чё-то не догоняю. Про compile-time оптимизации вычислений вроде понятно и согласен.
Ленивость достигнута за счёт построения дерева выражения и его интерпретации в run-time? Можно этого достигнуть в compile-time без написания дополнительного кода ленивых "генераторов"(например для суммы матриц), проблема в отсутствии поддержки компилятором? Или я чего-то не понимаю?
Потому что он вечный, очевидно же.
Потому что std::thread ты по-другому и не сможешь передать, у него нет конструктора копирования, так что хуй ты его скопируешь из обычной ссылки. Это и логично, ведь объекты std::thread это обертки, управляющие ресурсом системными тредами. И как их копировать, непонятно в общем случае - создавать еще один системный тред при каждом копировании в функцию противоречит логике приложения и вообще дорого, а разрешать нескольким оберткам ссылаться на один ресурс нельзя, т.к. тогда нарушится принцип владения когда вторая обертка попытается сделать join (), будет пиздец. Поэтому копирование просто запретили нахуй, как и для unique_ptr, например, тут в точности тот же принцип.
Ну не совсем так. У буста исходники оче неоднородные, часто встречается адское легаси, которому по 10 лет, и которое теперь бы сделалось гораздо проще, но переписывать никому не всралось. Предельный случай - умные указатели, которые теперь вообще добавили в стандартную библиотеку, они в бусте остались для совместимости вырвиглазными велосипедами. У встроенных STL реализаций, которые я видел, ужасающее форматирование с макросами и венгерской нотацией. Но в плане архитектуры годнота, да.
Я говорю конкретно про boost::ublas.
Ок, с самим принципом я немного разобрался, но не понимаю зачем его вообще копировать. Я ведь могу сделать так, верно?
void f(std::thread& t) {
...
t.join();
}
Могу предположить, что std::move нужно использовать не во всех случаях а именно тогда, когда по какой-то причине ты хочешь передать управление потоком? Только вот зачем это может понадобиться?
Можешь так сделать, пожалуй даже логичнее чем с std::thread&&.
Читай про && и moving semantics. С std::thread&& t ты можешь сделать
std::thread t2 = t без последствий, если я не ошибаюсь - т.к. копирования не будет, будет перемещение.
Спасибо.
>инициализируй объекты позже(например, запили метод Init())
Я так и делаю.
>А константы у тебя в каком смысле? Постоянны после создания объекта и разные для каждого экземпляра?
Да. В самом классе объявлены как const int. Значения задаются в списке инициализации конструктора. Если делать конструктор по умолчанию, то у меня их нужно будет сразу чем-то инициализировать. Пока сделал статическую переменную, которая отвечает за инициализацию по умолчанию, и статическую функцию, чтобы менять это значение. Примерно так:
[code]class myclass
{
private:
const int q;
static int q_default = 1;
public:
myclass(int n = q_default) : q(n) {}
static void change_q_default(int tq) { q_default = tq; }
};
...
myclass::change_q_default(5);
myclass t = new myclass[10];[/code]
Примерно так я сейчас работаю с созданием массива. Смотрится это не очень красиво, да и подводный камень в виде статичной функции, мне кажется, не комильфо. С другой стороны, у меня какая-то паранойя по поводу const. Я его пихаю везде, где могу, создавая себе при этом грабли вроде этого вопроса. Стоит ли так с этим заморачиваться?
>Тогда это не C++ const(они должны быть известны во время компиляции)
А что это тогда? Объявляются такие члены через const, инициализируются через список инициализатора конструктора. Не понял тебя.
> 2 варианта функции нет смысла делать
>компилятор проверяет, чтобы ты с const-переменными не работал не-const методами
Подожди, а если я объявлю объект const myclass, то мне понадобится иметь две функции, чтобы работать и с const и без них? Пример такой:
[code]const myclass a;
myclass b;
...
myclass &myfunc() { return this; } //в классе
...
b.myfunc(); //можно
b.myfunc() = a; //можно
a.myfunc(); //нельзя, но нет смысла делать такое ограничение[/code]
То есть в данном примере вполне можно было бы перегрузить эту функцию с const, чтобы оставить часть функционала. Или так не делают?
Спасибо.
>инициализируй объекты позже(например, запили метод Init())
Я так и делаю.
>А константы у тебя в каком смысле? Постоянны после создания объекта и разные для каждого экземпляра?
Да. В самом классе объявлены как const int. Значения задаются в списке инициализации конструктора. Если делать конструктор по умолчанию, то у меня их нужно будет сразу чем-то инициализировать. Пока сделал статическую переменную, которая отвечает за инициализацию по умолчанию, и статическую функцию, чтобы менять это значение. Примерно так:
[code]class myclass
{
private:
const int q;
static int q_default = 1;
public:
myclass(int n = q_default) : q(n) {}
static void change_q_default(int tq) { q_default = tq; }
};
...
myclass::change_q_default(5);
myclass t = new myclass[10];[/code]
Примерно так я сейчас работаю с созданием массива. Смотрится это не очень красиво, да и подводный камень в виде статичной функции, мне кажется, не комильфо. С другой стороны, у меня какая-то паранойя по поводу const. Я его пихаю везде, где могу, создавая себе при этом грабли вроде этого вопроса. Стоит ли так с этим заморачиваться?
>Тогда это не C++ const(они должны быть известны во время компиляции)
А что это тогда? Объявляются такие члены через const, инициализируются через список инициализатора конструктора. Не понял тебя.
> 2 варианта функции нет смысла делать
>компилятор проверяет, чтобы ты с const-переменными не работал не-const методами
Подожди, а если я объявлю объект const myclass, то мне понадобится иметь две функции, чтобы работать и с const и без них? Пример такой:
[code]const myclass a;
myclass b;
...
myclass &myfunc() { return this; } //в классе
...
b.myfunc(); //можно
b.myfunc() = a; //можно
a.myfunc(); //нельзя, но нет смысла делать такое ограничение[/code]
То есть в данном примере вполне можно было бы перегрузить эту функцию с const, чтобы оставить часть функционала. Или так не делают?
Ок, спасибо за ответы.
>везде нужны 10+ ЛЕТ ЗНАТЬ MFC BOOST WIN API JAVA C# VISUALSTUDIO и остальную никому НАХУЙ не нужную хуйню
Это не правда
Насчёт перегрузки функции с const. Видимо, я вспомнил свой код, потому что уже делал так. Как раз для того, чтобы можно было нормально работать с const объектами.
>>557565
Если принимается на вход/сама функция const - можно заюзать и с const переменной и с обычной без const. А вот const переменную за обычную не выдашь, если не делать говнокода с кастами(обычно следствие ошибок проектирования const-семантики). Поэтому лучше вообще без const, чем потом расхлёбывать ошибки, сляпаные на скорую руку, да и не всегда всё заранее получается продумать.
Внимание суть: QObject::connect(ui->verticalSlider, SIGNAL(valueChanged(int)), ui->lineEdit, SLOT(setText(QString)));
Ну вот смотри такой пример:
[code]class matrix
{
private:
...
vector pRow, pCol;
public:
...
const vector &operator=(const matrix&);
vector &operator()(unsigned);
vector &operator[](unsigned);
const vector &operator[](unsigned) const;
friend std::ostream &operator<<(std::ostream&, const matrix&);
};
matrix a;
a[1] = a(1) = a(2); //Ok
std::cout << a(1) << std::endl << a[1]; //Ok
const matrix b(a);
std::cout << b(1); //не работает
std::cout << b[1]; //работает за счёт перегрузки[/code]
Разве так плохо делать? Ведь мне всё равно нужна эта функция. Где здесь подводный камень?
Если ты не передаешь управление потоком, то получатель lvalue ссылки не имеет права сделать join. Потому что когда отправитель попытается удалить тред, join вызовется в деструкторе автоматически. В общем, если ты не владеешь тредом полноценно, а имеешь только ссылку, то тебе практически никакие действия с ним недоступны, только посмотреть id и т.п.
В любой вакансии, где кресты стоят в одной строке с шарпом или джавой, они не в действительности не нужны.
Этот человек сказал хуйню. const-функция и const-параметры вообще никак не связаны. const-квалификатор у функции может быть только, если это метод класса, и тогда это эквивалентно тому, что неявно передаваемый параметр *this объявлен как константный параметр. Константный метод может принимать неконстантные параметры и наоборот.
Делать >>557582 так хорошо.
Тем не менее, опыт МИНИМУМ 2 года, и это процентов 20 ваканский, в остальных требуют не менее 5.
Чем вообще пруфать опыт? Что вообще считается опытом два года? Опыт работы на фирме или самостоятельная тоже учитывается?
Вопрос решил сам
[CODE]signals:
void mySignal(QString);
public slots:
void mySlot(int value)
{
emit mySignal(QString::number(value));
}
QObject::connect(ui->verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(mySlot(int)));
QObject::connect(this, SIGNAL(mySignal(QString)), ui->lineEdit, SLOT(setText(QString)));[/CODE]
Если опыта не было, то никакие пруфы типа рекомендательных писем не прокатят все равно, ну только если интервьюер не даун. Если опыт был, то достаточно будет рассказать о своих проектах. Покатят и самостоятельные, и даже диплом какой-нибудь, если там годнота. Важно только что ты делал, а не где ты это делал.
У вас там что-то кроме аутсорса осталось? Если нет, то это, скорее всего, требование заказчика. А в таком случае, можно просто напиздеть - бодишопу-то похуй в общем-то, лишь бы себе жопу прикрыть.
В принципе, неплохой подход, подводных камней серьезных здесь нет. Но я бы сделал лучше пустой дефолтный конструктор, а потом инициализировал такие массивы отдельным методом. Это в перспективе будет быстрее всего, потому что позволит заполнить простейшие объекты вообще не поэлементно, а через memset, а для сложных объектов ты по-прежнему можешь присваивать что угодно поэлементно. В твоем же случае даже при дефолтном конструировании уже будут накладные расходы, что не оче хорошо, гибкости меньше, ну ты понел.
С помощью шаблонной магии можно много чего добиться, но я в такие дебри не лез никогда.
Спасибо.
>я бы сделал лучше пустой дефолтный конструктор, а потом инициализировал такие массивы отдельным методом
Ну у меня всё упирается в const. Но я тоже сейчас сделал конструктор по умолчанию, который инициализирует только const'ы (через статические переменные), а сама инициализация объекта осуществляется через отдельный метод. Это, конечно, быстрее.
Мне интересно, как это сделать "по-человечески", как в компилируемых/статически типизированных языках со встроенной "ленивостью"(насколько я знаю примером является Хаскель - сам его ни разу не пытался изучать). Чтобы к примеру для выражения Matrix c = a+b; генерировался ленивый генератор в compile-time. Про шаблонную магию наслышан немного, но это же еще тот изврат для этой цели, или я чего-то не понимаю?
Ленивость в энергичных языках пилится вручную - вместо реального вычисления выражения ты возвращаешь проксю, которая превращается в реальное только когда требуется. Во время этого вычисления в рантайме можно пройтись по expression tree и упростить его.
Как это сделать в compile time - хороший вопрос. Посмотри в сторону https://en.wikipedia.org/wiki/Expression_templates
Не уверен, что на самом деле сказал хуйню.
>const-функция и const-параметры вообще никак не связаны.
>тогда это эквивалентно тому, неявно передаваемый параметр *this
по-моему противоречит посылке, т.к. this - это просто неявный параметр функции и принципиально от других параметров не отличается. Если функция имеет в сигнатуре const typename& a, то можно передать любую typename foo, если имеет typename& a - то const typename bar уже не прокатит в качестве параметра, если я не ошибаюсь - т.к. внутри функции ты можешь изменить этот параметр, переданный по ссылке.
За это спасибо, не знал о такой технике. Мне интересно возможно ли чисто гипотетически, что в кресты встроят ленивые вычисления на уровне компилятора? Или это приведёт к куче новых проблем? Насколько я знаю, ленивые вычисления зародились в функциональных языках, можно ли перенести эту парадигму безболезненно на императивный язык?
Ну, в простейшем случае делается что-то такое:
[code lang="cpp"]
template <typename FirstType, typename SecondType, typename OutType>
class LazyOperation
{
\tFirstType first_; //Можно сделать ссылками, и будет быстрее
\tSecondType second_; //Но тогда они могут испортиться к моменту фактического вычисления
\t
\tOutType (operation_) (const FirstType &, const SecondType &); //Чтобы поддерживались различные сигнатуры, можно еще покумекать, но я простейшую концепцию показываю
\t
\tstd::unique_ptr <OutType> output_ptr_; //До фактического вычисления будет nullptr
\t
public:
\tLazyOperation (const FirstType & input_first,
\t\t\t\t\tconst SecondType & input_second,
\t\t\t\t\tOutType (input_op) (const FirstType &, const SecondType &)) :
\t\tfirst_ { input_first },
\t\tsecond_ { input_second },
\t\toperation_ { input_op }
\t\t
\t{}
\t
\toperator OutType () ()
\t{
\t\tif (nullptr == output_ptr_)
\t\t\toutput_ptr_ = make_unique <OutType> (operation_ (first_, second_));
\t\treturn output_ptr;
\t}
]
template <typename FirstType, typename SecondType, typename OutType>
auto makeLazy (const FirstType & first,
\t\t\t\tconst SecondType & second,
\t\t\t\tOutType (operation) (const FirstType &, const SecondType &)
{
\treturn LazyOperation <FirstType, SecondType, OutType> { first, second, operation };
}
[/code]
Это синтаксически не оче удобно, поэтому можно вынести реализации всяких +-*/ в отдельные функции, а вместо них перегрузить шаблонные по принципу makeLazy (), тогда 1+1 вернет LazyOperation <int, int, int>.
Таким образом, в compile-time построятся все эти классы ленивых операций, а вычисляться они будут только когда будет происходить приведение к неленивому типу, т.е. только в моменты использования.
Ну, в простейшем случае делается что-то такое:
[code lang="cpp"]
template <typename FirstType, typename SecondType, typename OutType>
class LazyOperation
{
\tFirstType first_; //Можно сделать ссылками, и будет быстрее
\tSecondType second_; //Но тогда они могут испортиться к моменту фактического вычисления
\t
\tOutType (operation_) (const FirstType &, const SecondType &); //Чтобы поддерживались различные сигнатуры, можно еще покумекать, но я простейшую концепцию показываю
\t
\tstd::unique_ptr <OutType> output_ptr_; //До фактического вычисления будет nullptr
\t
public:
\tLazyOperation (const FirstType & input_first,
\t\t\t\t\tconst SecondType & input_second,
\t\t\t\t\tOutType (input_op) (const FirstType &, const SecondType &)) :
\t\tfirst_ { input_first },
\t\tsecond_ { input_second },
\t\toperation_ { input_op }
\t\t
\t{}
\t
\toperator OutType () ()
\t{
\t\tif (nullptr == output_ptr_)
\t\t\toutput_ptr_ = make_unique <OutType> (operation_ (first_, second_));
\t\treturn output_ptr;
\t}
]
template <typename FirstType, typename SecondType, typename OutType>
auto makeLazy (const FirstType & first,
\t\t\t\tconst SecondType & second,
\t\t\t\tOutType (operation) (const FirstType &, const SecondType &)
{
\treturn LazyOperation <FirstType, SecondType, OutType> { first, second, operation };
}
[/code]
Это синтаксически не оче удобно, поэтому можно вынести реализации всяких +-*/ в отдельные функции, а вместо них перегрузить шаблонные по принципу makeLazy (), тогда 1+1 вернет LazyOperation <int, int, int>.
Таким образом, в compile-time построятся все эти классы ленивых операций, а вычисляться они будут только когда будет происходить приведение к неленивому типу, т.е. только в моменты использования.
Я к тому, что явные и неявные параметры не пересекаются.
А наслово поверят? Например если я скажу, что пилил игровые движки для своей игры века но всегда обсирался с контентом и сюжетом и геймплеем, поэтому мотивации все довести до завршенного продукта не было. Могу рассказать там о технологиях, что как было.
Тебя попросят рассказать детально о том, как пилил. Если ты на самом деле только книжки читал про это, то будет оче заметно, ибо тонкости не постичь на хэллоуворлдах.
Маловероятно. Максимум добавят какой-нибудь template class lazy в стандартную библиотеку. Такое, как видишь, очень легко реализуется на шаблонах, поэтому нет смысла перепиливать ядро.
Это будет вне идеологии С++, которая за zero overhead везде, где можно. Ленивость штука довольно тяжеловесная и непредсказуемая. Хотя ничего невозможного нет.
Только на линкедин или мойкруг какой-нибудь. Постить на сайты поиска работы это мегазашквар, если там висит твое резюме, значит, у тебя горит, и можно подешевле тебя купить, смекаешь?
Так и думал.
Вопросы такие:
Стоит ли начинать с C++? Или идти долбить Си, пхп, питон, мамку чью-то в доте, ect.
Как собственно учиться? Как происходит процесс изучения языка? Прочитал главу, сделал упражнения и усё?
Можно ли за год научиться C++ так, чтобы фрилансером маняработать? Или так можно только с пхп?
фл.сру, upwork, и т.д. открой. отфильтруй по цпп.
много интересных заказов?
да, конечно, после плюсов любая скриптодрисня осваивается за неделю, но толку? учи лучше питхон или жабаскрипт, или оба-два сразу
зы1. как вообще блять связано обучение ооп и плюсы?
зы2. никто тебя ничему не научить. гугли блять мудила
Научиться за год можно, фрилансерам как правило ничего сложного не отдают (а когда отдают то что-то связаное серьезными смежными знаниями, типа DSP и подобного). Проблема в том что работы для С++ фрилансера мало (хотя по расказам такие существуют). Смысл пхп не в том что в него за год научиться можно, а что там работы много, хоть и дешовой. Учить плюсы стоит только если ты понимаешь зачем они тебе нужны. У них ограниченая сфера применения, работы не так много, просто так их учить мало смысла. Даже ради учебы на будущее - если есть способности к програмированию то проблем с учебой быть недолжно даже без подготовки. Возможно тебе стоит взятся за шарп или джаву. Шарп лучше, но на нем чуть меньше вакансий и анальная привязка к виндовс, по крайней мере пока.
>>557758
Постарайся читать чужой код. Ну и естественно кодить самому. Помоему для ньюфага идеально сесть на готовый проект и чистить вилкой баги. но если ты один то хуй знает где такое найти.
Я не учился кодить по книжкам. Моим первым языком был QBasic и я изучал его лет в ~12 по англоязычной документации с подстрочником, смотрел примеры кода там, писал нубопрограммы. Не сочтите за понты, плиз.
Помогли некоторые университетские курсы(лекции по основам, структурам данных, общение с толковыми дядьками). Если хочешь самостоятельно освоить - вкатывайся в coursera(или что-то подобное) с кем-нибудь на пару и начинай задрачивать. Пиши свои программы-велосипеды(выбирая нравящуюся тематику) и как можно больше, как в случае с математикой - читая чистую теорию и не решая задач её не понять, так и с программированием. Еще можешь профессиональные примеры брать и читать. Stackoverflow используй везде, где можно.
>>557757
Не стоит вкатываться в кресты если ты новичок, имхо. Лучше изучи чистый C(и то опционально) и питон/Java/C#, дальше по вкусу - если веб - то можно навернуть php, веб-фреймворков в python.
>Можно ли за год научиться C++ так, чтобы фрилансером маняработать
Да в принципе возможно всё, но лучше так не делай.
C++ - язык для бородачей-байтоёбов(в хорошем смысле слова) и фанатиков. Хотя если ты очень мотивирован, то тебя это не остановит. Вкатывайся уж лучше в няшный и мелкомягкий C#.
>Как собственно учиться? Как происходит процесс изучения языка? Прочитал главу, сделал упражнения и усё?
Синтаксис языка - это только верхушка айсберга. Чтобы писать программы нужно знать "базу", не зависящую от языка - хотя бы "кухонную"(структуры данных, алгоритмы, архитектура ОС и приложений для чайника, ООП, не помешало бы еще несколько концепций-парадигм).
Ну так лучше быть фанатиком с глубокими знаниями, чем макакой, который едва осилил жабу и ждет, что ему сборщик мусора жопу подотрет. Там выше была ссылка на статью Спольски про протекающие абстракции, в ней разжевано, почему не выйдет быть высококлассным специалистом, зная только высокоуровневые абстракции.
>Ну так лучше быть фанатиком с глубокими знаниями, чем макакой, который едва осилил жабу и ждет, что ему сборщик мусора жопу подотрет.
В таком ракурсе конечно лучше. Но среди макак попадаются смышленные экземпляры, способные в профессиональное саморазвитие и самообучение - вот что главное, поэтому кресты не панацея. Знание крестов не сделает автоматически тебя кулхацкером, как многие ньюфаги представляют.
А они все братья? Можно ли выучив C# на уровне "Только для pro на fl.ru" потратив пару месяцев перейти в java, C++, php. Они же вроде сиподобные.
Хочется в чужом коде поразбираться, рыл гитхаб - нихуя годного нету по крестам.
У них только синтаксис подобный. На деле разные языки, у С++ нет сборки мусора и из-за этого куча суровых идиом, C# или Java в общем-то друг друга копируют, php - динамический язык.
Лучше быть тем, кто хорошо решает задачи. С С++ ты не научишься настраивать сборщик мусора, поэтому учить С++ ради Java - глупо, хотя сишку нужно знать, конечно.
>Знание крестов не сделает автоматически тебя кулхацкером
Воистину. Вся проблема в том, что не существует т.н. БЫСТРОГО ПУТИ. Чтобы разбираться, в любом случае придется хлебнуть низкоуровневого говнеца. Многие ньюфаги думают, мол, потом хлебну, если понадобится, а сейчас выучу одноглазого или жабу по-быстрому и пойду рубить бабло. А это очень опасная иллюзия. У того, кто впервые начал серьезно погроммировать на управляемых языках, или, что еще хуже, на динамической параше, мозги оказываются напрочь зашкварены. Потом требуются годы усилий, чтобы суметь в низкоуровневость, переучиться-то гораздо сложнее, чем научиться с нуля. При всей порочности стандартного университетского набора CS-курсов их составляли далеко не дауны, при их прохождении именно что ставится правильное мышление, именно поэтому на начальных этапах вообще учат на мертвых языках типа Паскаля. Суть не в том, чтобы сразу научить сосницкого делать продакшен-код на Паскале, а в том, чтобы научить его алгоритмам, не засрав при этом мозги динамической парашей. Не потому что динамическая параша это плохо, а потому что юный мозг без низкоуровневых знаний не способен в полной мере понять все нюансы, из-за чего он начнет упрощать полученные знания, пытаясь встроить их в свой пока еще скудный манямирок. И таки встроит, но встроит неправильно, на выходе получится дичайшая каша, которую потом хуй вычистишь из головы. Поэтому, кстати, выбрали монструозный Паскаль со строжайшими требованиями, который держит погроммиста за яйца постоянно. После этого обучают ассемблеру, pure C, крестам, а уж затем у сосницкого срака как у дональда дака достаточно крепкое ощущение того, что хорошо, а что плохо, чтобы можно было безопасно вкатываться в любой язык, какой только душе угодно.
C++ это плавный переход, когда низкоуровневость еще есть, а пряники типа ООП и исключений уже есть. Ну и мощный он, поэтому многие на нем остаются.
>OpenCV
>годный код
>int \tcheckOptimalVectorWidth (const int *vectorWidths, InputArray src1, InputArray src2=noArray(), InputArray src3=noArray(), InputArray src4=noArray(), InputArray src5=noArray(), InputArray src6=noArray(), InputArray src7=noArray(), InputArray src8=noArray(), InputArray src9=noArray(), OclVectorStrategy strat=OCL_VECTOR_DEFAULT)
Почему параметров не 8, не 10, а 9? Это по числу кругов ада, или число планет в солнечной системе, или что? Кто мешал принимать метавектор этих параметров, либо через шаблонный параметр передать их количество, если байтов жалко?
Это платина
Ты подумай, что будет удобнее всего в коде с учетом того, что код у тебя динамически линкуется (т.е. шаблоны не рекомендуются)?
В этой функции наверняка простейший проход по параметрам в пять строчек, ее сам б-г велел вынести в хэдер, так что шаблоны не проблема. А в их случае я либо получаю либо 28 байт оверхеда при каждом вызове, либо вообще не могу ее применить, если мне вдруг захочется для 10 векторов сделать.
Ложка дёгтя всегда найдётся в достаточно большой бочке мёда. Закон жизни и кодинга.
Странный ты какой-то, взял бы да и посмотрел. Внутренности тебя испугают еще больше, потому что там пердолится препроцессор. https://github.com/Itseez/opencv/blob/190d00ea3e46feedd38a7417c0a5ab08b900a56b/modules/core/src/ocl.cpp#L5789
10 векторов бессмысленно, так как это часть модуля ocl (т.е. OpenCL), а там есть ограничение на количество входных переменных, не все видюхи это тянут.
>>557833
В OpenCV говна хватает, но это даже и хорошо. Я бы мог посоветовать clang или вообще V8, но там-то подохуеешь малясь.
>zero overhead
Что это значит? Гуглить и читать сил уже нет, объясни в двух словах по-русски.
мимо-говнокодил
Вопрос действительно туповато сформулирован. Если это массив непрерывного хранения в памяти T[] или string, vector -- то, очевидно, индексация не может быть изменена для операции типа swap.
Велосипедно это выглядит так:
T temp = v_1;
v_1 = v_2[j];
v_2[j] = temp;
но в реализации STL наверняка хитрее как-нибудь с ассемблерными хитростями
1) тупо указатель на char[] (неважно, в куче или на стэке) -- зачем -- sizeof(char) == 1, чтобы аллокацию делать не более байта на 1 значение, небольшая экономия, если sizeof(bool) != 1;
2) std::vector<char> -- зачем -- чтобы не мучаться с битовыми полями, std::vector<bool> криво стандартизирован.
Кстати, не находил примеров использования std::vector<bool> в сети. Кто подкинет может, чисто из удовлетворения любопытства на ночь глядя.
Индексы могли бы поменяться, если бы у тебя была сущность "индексатор"(её можно реализовать в виде массива указателей, к примеру). Для обычных массивов её нет, индексация всегда одна.
Смотря что у тебя за булевые значения(однородны ли они по семантике, например). vector<bool> вполне хорош для своей цели, просто некоторые адиёты не понимают, для чего он нужен и как им правильно пользоваться, а также почему он так отличается от других контейнеров(оптимизация, сэр). Vector<bool> экономит память раз в 8, но работает медленнее из-за побитовых операций(которые сами по себе очень быстрые по сравнению с другой арифметикой).
>>557963
Это значит нулевые накладные расходы(здесь: на реализацию какой-то возможности) - соответственно максимальный перфоманс/минимальная прожорливость.
А и еще - vector<bool> более плотно хранит данные, соответственно будет выигрыш на кэше в случае большого вектора.
Ты в принципе прав, только переучиться реально легче, чем научиться. Вот правда.
Это не самый плохой код для расчетов, хотя бы переменные по-английски названы и vector используется.
Спасибо, но ты не на те вопросы отвечаешь. Я сам использую собственные велосипедные битовые операции для своих целей (плотной упаковки больших объёмов информации перед записью на жёсткий диск), причём вполне осознанно пишу 1U, а не 1. Приведу намеренно упрощённый пример в предположении, что source_size % 8 == 0 и source_size / 8 == destination_size и destination изначально полностью занулён:
>for (std::size_t j = 0, k = 0; k < destination_size; ++k)
> for (int m = 7; m >= 0; --m, ++j)
> if (condition(source[j]))
> destination[k] |= 1U << m;
Поэтому про плотную упаковку мне можно не рассказывать. Ситуация у меня следующая: есть значения, требующие плотной упаковки. А есть массив булевых значений не столь большого размера, для которого нужно найти компромисс между скоростью работы и упаковкой в оперативной памяти.
bool[] мне кажется не вариант, т.к. бывает sizeof(bool) == 4
плотная упаковка совсем не вариант, т.к. этот массив используется для собственно вычислений, часто и долго
вот и думаю остановиться на char[] и писать туда значения не 0 и 1, а false и true (для большей читаемости кода), спрашиваю, не просядет ли скорость в сравнении с bool[] -- это первый вопрос, и если просядет, то насколько
Второй вопрос: можно мне примеры использования std::vector<bool>, а то не видел ни разу. Требуется ли #include <bitset> для std::vector<bool>?
И это - небольшого размера? В программировании есть несколько размеров, определяемых только размером ОЗУ:
1. Помещается в регистр.
2. Помещается к кэш L1
3. Помещается в L2/L3.
5. Влазит на жесткий диск.
6. Твоя мама.
Расскажи про
>1. Помещается в регистр.
>2. Помещается в кэш L1
>3. Помещается в L2/L3.
4, 5, 6 меня очевидно не волнуют. Что там в типичных значениях килобайтах / мегабайтах для 1, 2, 3? И да, я в любом разе выделяю при помощи new[] / delete[], если это важно.
А может ты преждевременно оптимизируешь? С чего ты решил, что bottleneck будет именно в наборе bool? Твоя программа проводит бОльшую часть времени на операции с этим набором? Может выбор контейнера вообще незначим будет в контексте всей программы(программа проводит относительно мало времени на коде с булями). На крайняк напиши оба варианта и проведи benchmark. Про vector<bool> вот http://www.cplusplus.com/reference/vector/vector-bool/
>А может ты преждевременно оптимизируешь?
Определённо да, но просто всё остальное уже оптимизировать некуда или невозможно. Это программа уровня laba2, по сути.
>>558171
>Про vector<bool> вот http://www.cplusplus.com/reference/vector/vector-bool/
Мне бы примеры кода, братишка. Ни разу в жизни нигде не нагугливал, даже на stackoverflow. Ну и помимо #include <vector>
>>Требуется ли #include <bitset> для std::vector<bool>?
vector<bool> - это такой же вектор как и vector<%typename%>, не нужно тебе примеров кода. Все "подводные камни" есть по ссылке.
Самое основное
>A special member type, reference, a class that accesses individual bits in the container's internal storage with an interface that emulates a bool reference. Conversely, member type const_reference is a plain bool.
The pointer and iterator types used by the container are not necessarily neither pointers nor conforming iterators, although they shall simulate most of their expected behavior.
Т.е. если тебе не нужны ссылки на отдельные биты - вообще проблем/отличий никаких быть не должно.
Презентация с пары на военке? Тебя же расстреляют, дурачок, это секретные материалы. У нас одному чуваку чуть госизмену не пришили за то, что тетрадку вынес.
Правда. Физфак МГУ, год примерно 2005. Даже гуглится вроде.
int@ array_1 = new int[array_1_size];
int@ array_2 = new int[array_2_size];
/
do something...
/
delete[] array_1;
delete[] array_2;
Или вообще без разницы (размещение и освобождение идут соседними инструкциями, как видно из кода).
Никакого значения это не имеет, потому что в случае, если кто-то бросит исключение, память у тебя потечет как твоя мамка. Всегда выделяй память в конструкторе и освобождай в деструкторе. Всегда.
В общем случае - имеет. Аллокация/освобождение памяти довольно дорогостоящая операция, завязанная на ОСь и системные вызовы(без кастомных аллокаторов, создающих дополнительный слой абстракции), поэтому твой поток выполнения может заблокироваться на значительное в некоторых случаях время. В остальном - разницы нет. Главное, чтобы ты указатели на удаленную память не использовал, и освобождал её вовремя(точнее, чтобы была гарантия того, что она освободится во время выполнения).
Про исключения тебе правильно сказали, это один из геморроев исключений.
Итератор в глубину делается на раз. По ширине могу только школьным методом со стеком пройтись в какой-нибудь функции, но запилить operator++ в ширину при этом избегая перегенерации стэка каждый раз не получается. Завести protected указатель на стэк что-ли, к которому обращаться при ++ и перегенерировать при =?
>вкатывайся в coursera(или что-то подобное) с кем-нибудь на пару
Так вот и нет пары. Только книжки и тырнет. Начал пока пилить задания отсюда: http://math.sgu.ru/sites/chairs/prinf/materials/java/maintask.htm с гуем от Qt, а там как придрочусь чутка думаю свой плеер набыдлокодить. Пойдет под велосипед, думаю.
Чую надо было не выебываться и учить какую-нибудь джаву, но раз уж начал.
> но запилить operator++ в ширину при этом избегая перегенерации стэка каждый раз не получается.
Почему?
Не знаю как. Чуть что где поменялось и ты уже пропустил ветку, приходится всё дерево снова просматривать. Или допустим охота проходить по очереди в глубину и в ширину.
Я бы вообще не стал итерировать классическое дерево, в котором не хранится параллельно остовный список, это слишком накладно. Даже в глубину ты не сможешь дать гарантию константного времени для ++, а уж в ширину и подавно. Если ты посмотришь реализации красно-черных деревьев в STL, то увидишь, что там везде для итерации используется остовный список, а по самому дереву никто и не думает ходить так. Тем более, что для эффективной реализации своего велосипедного итератора тебе по-любому придется хранить стек пройденного, так не лучше ли хранить остовный список и не выебываться?
Перегенирировать стек не надо. Тут, кажется, вообще не нужен стек(если только ++). На этапе уровень n - проходишь по всем потомкам данной вершины, кладёшь их в массив. Далее повторяешь операцию. Завершаешь тогда, когда потомков нет. Для -- нужно запоминать в стеке "уровни", а не вершины(как я понимаю).
Правильно делать так: под каждый ресурс , включая память, файлы, хэндлы ОС и т. п. ты делаешь класс, который захватывает его в конструкторе и освобождает в деструкторе. В таком случае брошенное исключение
1. В конструкторе - ты не успел захватить ресурс, поэтому и свобождать его не нужно.
2. В коде - при бросании исключения из функции автоматом будут вызваны деструкторы всех объектов в текущем скоупе.
3. В деструкторе - исключение в деструкторе вызывает падение программы, поэтому ты обязан предусмотреть все.
Т.е. в данном случае нужно использовать std::vector и не париться с new и delete вообще.
И да - это всё довольно накладно, чтобы избежать стека возможно лучше хранить в вершине предка, либо запилить дополнительную структуру, если итерировать нужно часто.
Иными словами, ближайшие годы, пока ты не дорастешь до собственных аллокаторов, писать new и delete тебе не нужно.
А если мне нужно захватить два ресурса в конструкторе, а при захвате второго будет исключение? Тогда деструктор вызовется?
Итераторы традиционно инвалидируются при изменении стуктуры данных. По очереди - ну хуй знает, это уже не итератор получается.
Не захватывай два ресурса в конструкторе, напиши мини-класс, который захватывает 1 ресурс. На самом деле они уже написаны и есть в стандартной библиотеке - это контейнеры stl и умные указатели.
unique_ptr в 0x11 вроде ОК. Пока не разбирался в этом вопросе.
Прочитай ещё и где именно их плохо использовать.
Твои книги устарели.
auto_ptr неудачный класс из стандарта 1998 года, он действительно не рекомендуется, потому что у него нет счетчика ссылок, но при этом его можно копировать. Т.е.
{
std::auto_ptr<A> a(new A);
std::auto_ptr<A> b(a);
}//здесь вызываются деструкторы и память пытается освободиться дважды, программа падает.
Используй unique_ptr и shared_ptr.
unique_ptr - без счетчика ссылок, но его копирование запрещено. Вместо копирования разрешен только перенос (с помощью std::move). Случайно двойного удаления не получится
shared_ptr - со счетчиком ссылок и им может владеть много объектов. При копировании счетчик ссылок увеличивается, в деструкторе - уменьшается. Если в деструкторе счетчик ссылок равен нулю, память освобождается. Здесь проблемой являются только циклические ссылки - когда объекты ссылаются друг на друга, память может потечь. Решается это с помощью грамотной архитектуры и weak_ptr.
weak_ptr похож на простой глупый указатель, он памятью не владеет. Это чисто костыль для циклических ссылок.
Умные указатели это не только auto_ptr
Меняется не дерево а указатель итератора. Например дошёл итератор от начала до вершины А и прыгнул к вершине Б (не проитерировал, а прыгнул, Б может быть как выше, так и ниже А). Как потом перейти к другим вершинам того же уровня не бегая сорок лет по родителям и не перегенерируя весь стэк?
>>558270
Это и есть тот школьный метод со стеком (только ты его называешь массив), и как ты его описал он будет пробегать (в ширину, да) только по потомкам данной вершины, а не по всем вершинам уровней.
Вот есть алгоритм обхода из гугла (к своему стыду я не знаю как это будет по-английски):
while стек $S$ не является пустым do
Пусть $p$ -- вершина, находящаяся на верху стека $S$;
if Сыновья вершины $p$ еще не посещались
then Посетить старшего сына вершины $p$ и поместить его в стек $S$
else
Удалить вершину $p$ из стека S;
if$p$ имеет братьев then Посетить брата вершины $p$ и поместить его в стек $S$end
end
end
Чтобы превратить его в итератор, локальные переменные алгоритма делаешь переменными объекта. while выкидываешь и превращаешь его внутренности в operator++. Усе.
Т.е. как я писал в >>558242
>Завести protected указатель на стэк что-ли, к которому обращаться при ++ и перегенерировать при =?
?
Мне вот больше про остовный список понравилось. Перегенерировать при изменении дерева, ходить стандартным списковым итератором, лепота.
Только вот два вопроса:
1) где хранить список? В классе дерева или итератора?
2) Если хранить его в дереве, то как избежать его создания в случае если итератор не нужен, а если в итераторе то как перегенерировать список если изменяется дерево?
>Если хранить его в дереве, то как избежать его создания в случае если итератор не нужен
Ленивой инициализацией. Делаешь private поле класса "list<yoba> mylist" неинициализированным, а public функции getList проверяешь, инициализировано ли оно, и если нет, то инициаилзируешь. Универсальный паттерн.
>а если в итераторе
А если у тебя итератор находится в том месте, которое ты удалил? Просто должно быть запрещено использование итераторов после того, как дерево изменилось (инвалидация). Иначе охуеешь.
Стек у тебя в итераторе лежать будет. Если хочешь геморройно сэкономить - ограничься одним итератором в любой момент времени и храни его в дереве вместе с итератором, например.
Тебе его даже не понадобится перегенерировать, если ты хранишь в дереве указатели на вершины, и при изменении дерева фактические адреса вершин не изменятся. Тогда достаточно будет при добавлении элемента в дерево вставить один элемент в список, за константное время. С удалением то же самое.
Узел на концептуальном уровне:
[code lang="cpp"]
class Node
{
//...
Node parent;
Node children [];
std::unique_ptr <Key> data;
//...
}
[/code]
Поменять местами две ветки ~ поменять местами два указателя. Остовный список при этом не изменится вообще, потому что он оперирует только объектами Key, которые не меняют адрес вообще, какие бы ты операции над деревом не делал.
Они более сырые пока что.
>В общем случае - имеет.
Ну так как лучше в моём случае: сначала улаоить первый, который раньше создали (он больше по размеру), или сначала удалить второй, который позже создали?
Да, тупой. Я понимаю, что вы имели в виду под "не бывает new без деструктора объекта, чтобы не было утечек", но не умею в классы.
#include <vector>
...
std::vector<int> array_1(array_1_size);
std::vector<int> array_2(array_2_size);
Все.
Врунишка
>>558238
А ты хуйнйю сморозил, твой пример имеет место быть, если работать с кучей говна напрямую, через WINAPI, если же использовать средства С++, то память выделяется и освобождается довольно быстро но не как на стеке. И проблема может возникнуть лишь при многопоточности, когда несколько потоков используют один аллокатор.
Иногда проводят, а иногда не проводят. Не стоит обожествлять компиляторы, вот почитай какой-нибудь листинг, и сразу много нового узнаешь.
new - это уже оверхед, тебе нужен собственной аллокатор.У тебя явно не те скорости.
>> for (int i = 1; i <= n; ++i) {...}
Если в такой записи i уйдёт за пределы интежера, что произойдёт?
Изучи, что такое дополнительный код. http://ideone.com/y7rHRz
В случае int будет то же самое, но переполнение будет не при 2^7, а при 2^31.
Если в C или C++ случается overflow в signed типе, то есть например при операции сложения получается результат, не влезающий в числовой тип, то, что при этом случится, стандартом не определено (это называется undefined behaviour)
Лол, неплохо.
>А ты хуйнйю сморозил, твой пример имеет место быть, если работать с кучей говна напрямую, через WINAPI
Просвети меня, как работает generic new, он что -использует промежуточные аллокаторы по умолчанию? Так или иначе системные вызовы будут, у тебя же многозадачная ОСь с кучей других процессов, выделяющих память запущены. Да и сам алгоритм стандартной кучи(поиска нужного фрагмента памяти) довольно затратный, но тут решает скорее переключение user-kernel-space и всяческие блокировки.
А ты думаешь ты при new запрашиваешь целые старницы памяти у системы что ли? Конечно используется промежуточная структура данных внутри программы, куча называется. https://ru.wikipedia.org/wiki/%D0%9A%D1%83%D1%87%D0%B0_(%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C)
Можно ли увеличить массив? Нужно складывать неизвестное кол-во значений куда-то, но не знаю как.
Да, видимо я глубоко заблуждался. Всегда думал, что куча для отдельных процессов на уровне ядра ведётся, а "локальной" кучи процесса нету.
Можно - если массив пересоздавать, копировать и удалять старый. Но лучше использовать готовое решение из коробки:
#include <vector>
Давно бы пора ему в Элериум-115 превратиться.
Это дорого, и вообще, на крестах так не пишут. malloc/calloc/realloc/free это функции из стандартной библиотеки C, которая оставлена для совместимости.
По-моему вызвать v.resize() требует меньше мозгов, чем разбираться с realloc. А так realloc может быть даже эффективнее, если повезет. Я помню блогпост какого-то сишного говноеда, который доказывал жуткую неэфективность vector с помощью сравнения кучи ресайзов подряд с кучей realloc подряд.
Ну использовал бы fbvector тогда, или в крайнем случае написал бы свой велосипедный. Говноедство-то с realloc без обертки зачем?
Ты вообще конченный?
ой бля, еще одна макака, неосилившая структуры данных
>Нужно складывать неизвестное кол-во значений куда-то
юзай <list> , люк
Потому что ты это только что выдумал?
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
Сохраняешь это строку в файл.
Во-первых ifstream, ofstream буферизованы.
Во-вторых есть функция getline(string, stream), которую очень просто написать самому - сначала читаешь до ',', потом до '\n'. Строки склеивать в памяти не надо, просто последовательно пиши их в поток. И не используй endl с файлом, используй '/n', т.к. endl вызывает flush потока(если я не ошибаюсь). Вбрось код, который ты написал на циклах - посмотрю что там у тебя тормозит.
В-третьих на stackoverflow пишут, что если нужно еще больше скорости - юзай C-потоки с ручной буферизацией/memory-mapped I/O(можешь взять из Boost) - но это будет слишком геморройно для laba.cpp.
В-четвертых ты можешь полностью считать файлы в память - но это не совсем "красиво" и будет отжирать память для больших файлов/невозможно будет открыть очень большие файлы.
1.) Запустить параллельно несколько программ с разными входными данными, если это возможно.
2.) Взять исходный код программы и переписать/дописать её("распараллелить").
Есть запись на диск, вывод на экран, выход в сеть? У тебя скорее всего на что-то внешнее проебывается время - расчеты не идут постоянно, а ждут какой-то хуйни.
Точнее - у него 4 логических процессора. Это может быть двухпроцессорная система с 2 ядрами, но вероятнее всего - четырёхядерный таки, как бабка Ванга сказала.
И всё-таки. Поди unique_ptr оверхэдов не даёт в сравнении с std::vector, правильно я понимаю?
Когда использовать unique_ptr, а когда std::vector?
Ты немного попутал тёплое с мягким. Unique_ptr позволяет запилить RAII на месте, без написания своего класса. Vector - это структура данных типа "динамический массив" - последовательный контейнер с константным случайным доступом к элементу, прочитай про него - инфы море. Vector по сравнению с массивом почти не даёт оверхеда, зато добавляет функциональности(продуманное авторасширение массива при добавлении элементов, всякие вставки-удаления и так далее). Есть очень небольшой оверхед на доступ к элементу из-за вызова функции, но он может быть оптимизирован компилятором чуть ли до 0(заинлайнить функцию).
>>558888
Толсто.
>Как тут замечали выше, нам бы без оверхэдов.
>Когда использовать unique_ptr, а когда std::vector
Он же совсем дебил, какие ему оверхеды, если он не владеет ситуацией и не имеет никаких знаний.
>но не умею в классы.
>спрашивает в каком порядке удалять массивы.
>пишет laba1 для строительного пту.
Квадрипл врать не станет.
Я примерно прикинул как могу распараллелить разные циклы, но если я сейчас всё раскину на два потока, будут ли проблемы при запуске на пеках с другими конфигурациями? Например, допотопном ноуте.
>Ты немного попутал тёплое с мягким. Unique_ptr позволяет запилить RAII на месте, без написания своего класса. Vector - это структура данных типа "динамический массив" - последовательный контейнер с константным случайным доступом к элементу, прочитай про него - инфы море. Vector по сравнению с массивом почти не даёт оверхеда, зато добавляет функциональности(продуманное авторасширение массива при добавлении элементов, всякие вставки-удаления и так далее). Есть очень небольшой оверхед на доступ к элементу из-за вызова функции, но он может быть оптимизирован компилятором чуть ли до 0(заинлайнить функцию).
Ну так я могу использовать как unique_ptr, так и std::vector, чтобы избежать утечки памяти в случае исключений. Вот и спрашиваю, что производительнее.
P.S. Весь сахар типа .size() и прочего мне вообще не нужен, я передаю все необходимые параметры в функцию явно, т.к. они нужны в этой функции и помимо цикла for с размером массива. Расширения массива точно не будет.
Существует три популярных способов параллелить вычисления: стандартные треды, OpenMP и SIMD векторные инструкции. Треды позволят тебе вообще не думать о платформе, ибо это часть стандарта, но они дадут выигрыш, только если ты можешь разбить задачу на относительно большие, ибо создание треда все-такие не самая дешевая операция. OpenMP поддерживается основными компиляторами и позволяет автоматически параллелить циклы. Преимуществом является дешевость, а также то, что весь код оформляется в виде директив #pragma перед нужными циклами, т.е. если даже компилятор не умеет в OpenMP, код нормально скомпилируется и будет выполняться последовательно. Наконец, у разных процессоров есть SIMD-расширения, когда ты делаешь одну операцию над векторами вместо отдельных переменных и можешь за одну итерацию цикла обработать несколько значений массива, например. Они вообще не вызывают накладных расходов на создание каких-либо тредов, но проблема в том, что писать на них довольно утомительно смахивает на асм, и никакой переносимости нет в принципе. Меняется процессор - ты сосешь. Выбирать вариант тебе, но я бы посоветовал грамотную архитектуру и первый, ускорение получается более чем достойное, а ебаться не надо. Если тебе надо еще быстрее, то подумай о том, что 20% производительности тебя не спасут, и лучше в этом случае перейти на какой-нибудь OpenCL с расчетами на GPU.
ТЫ точно дебил. unique_ptr хранит лишь указатель на объект и запрещает копирование самого себя. А vector это целая структура данных, внутри которой множество всякой хуйни в виде внутренних функций. Вкратце, я виви используй unique_ptr.
Блядь, ну хуле ты тупой такой? Ежу понятно, что он хочет хранить массив и имеет в виду выбор между vector и unique_ptr = new [].
Это ты тупой, unique_ptr не несет в себе оверхеда, это обертка под шаблонный указатель, а vector это огромный класс с множеством всякой хуйни. Он блять даже в базовых понятиях не ориентируется.
Так какой оверхед у вектора, если это шаблонный класс? Ты правила инстанцирования учил, чепуш? Если он не будет юзать методы вектора, то они и не сгенерируются. Конструктор и деструктор там инлайновые вообще, opeartor [] тоже.
Граждане, я готов подписать себя под абсолютного дебила и принять рекордную порцию мочи, только давайте уже придём к единому мнению, и не путём обзывательств, а путём аргументации.
1. Первый вопрос. В конечном итоге что и где даёт оверхэд? Я так понял, unique_ptr это тупо экземпляр класса, в котором есть деструктор, который вилкой чистит память при гибели указателя. Минимальный оверхэд или нет? А у вектора?
2. Нужно ли #include <new>, если уже есть #include <memory> ? Не нагугливается.
#include <new> это нонсенс, ибо new это не библиотечная функция, а встроенный оператор. Если ты не обращаешься к operator new напрямую из самописного аллокатора, тебе не нужен этот хедер.
Если ты прям никогда не будешь менять размер своего массива, то стоит использовать unique_ptr, ибо оверхеда не будет вообще. В векторе же хранится 8 лишних байтов на size и capacity, причем, если size тебе, возможно, понадобится в случае в unique_ptr придется хранить его самостоятельно, то capacity для неизменяемого вектора будет лишним, просто повторяя size.
Оверхед - "добавочные" поля вектора(8 байт, а то и 4 т.к. если у тебя массив переменного размера, тебе тоже надо хранить длину) и оверхед вызова функции(передача параметров/новый стековый фрейм) при использовании методов vector. Но это решается inlining'ом функций, как сказал >>559064.
Алсо, в векторе как правило должны быть незанятые ячейки в конце - чтобы избежать лишних перевыделений памяти - но в случае фиксированной длины, ты просто обрезаешь capacity до значения size.
Еще есть увеличение размера исполняемого кода программы из-за дополнительного кода(методов vector), который оверхедом-то считать нельзя - как сказали выше, по правилам инстанцирования.
В общем оверхед копеечный если не нулевой вообще - особенно при оптимизациях компилятора(чтобы был inlining методов), можно бенчмарк провести - я думаю уже кто-то написал его наверняка.
>#include <new> это нонсенс, ибо new это не библиотечная функция, а встроенный оператор
Я, видимо, чего-то неправильно понимаю.
http://www.cplusplus.com/reference/new/operator%20new[]/
http://en.cppreference.com/w/cpp/memory/new/operator_new
>Defined in header <new>
Есть оператор new, а есть библиотечная функция с именем operator new. Оператор встроен в ядро, не требует никаких хедеров и вызывает одну из перегруженных функций operator new, по умолчанию это будет как раз та, что объявлена в <new>. Короче говоря, это просто вопрос терминологии, тебе нужно сейчас просто знать, что если ты нигде в программе не пишешь словосочетание "operator new", то тебе не надо ничего подключать.
>Если ты прям никогда не будешь менять размер своего массива
Именно так. Более того, его неизменный размер известен задолго до этапа компиляции, и если почитаешь предыдущий тред, то там был ряд интересующихся (олимпиадников и прочих калек) размещением массивов на стэке. Нас дружно обоссали, и я пришёл в этот тред за свежей порцией мочи по поводу надлежащей работы с памятью.
>>559103
Прошу прощения за тупейший вопрос, а std::bad_alloc в случае чего для unique_ptr не понадобится? Он-то уж точно определён в <new> (поправьте, если опять ошибаюсь).
Так ты тогда вообще хуйню творишь. Если размер этого массива сравнительно небольшой скажем, меньше 10 килобайт, то его сам б-г велел выделить на стеке я вроде упоминал про это в прошлом треде. И в этом случае ты можешь получить вообще нулевой оверхен, используя std::array <size>.
>Более того, его неизменный размер известен задолго до этапа компиляции
Без оверхеда легко сделать. Запилить шаблонный класс с целым параметром и полем-массивом, инстанцировать и поместить в глобальные переменные, к примеру. Тогда массив будет храниться на статическом хранилище, выделенном во время компиляции(это даже быстрее, чем стек).
>>559112
Кури параметры компилятора. У vs вроде есть в настройках чё-то про inline - то, что компилер даже будет пытаться встроить функции без inline, которые посчитает нужным. Еще зависит от флага оптимизации по-моему и того, как линкуется библиотечный код(статически или динамически)
Если кто-то в коде нижнего уровня бросил исключение хуй пойми какого типа, то ты не обязан подключать соответствующий хэдер, чтобы обработать его, если тебе не нужны специфические знания об этом типе. Ты можешь поймать его по ссылке на базовый класс std::exception и использовать только общее для всех исключений поле what. Или можешь поймать по ... и поставить какой-то универсальный обработчик, который ничего не знает о типе исключения. Или можешь ничего не ловить и пропустить исключение наверх. Подключать следует только в одном случае - если этот тип исключений содержит какую-то специфическую инфу, которую тебе следует достать при обработке. Но bad_alloc вообще ничего не содержит специфического, так что подключать что-либо имеет смысл только если ты сам бросаешь этот тип исключения.
>Тогда массив будет храниться на статическом хранилище, выделенном во время компиляции(это даже быстрее, чем стек).
А вот здесь можно поподробнее? Это подойдёт для очень больших массивов (мегабайт и больше)?
Это лажа в духе глобальных переменных, у тебя не сможет быть больше одной копии такого массива на программу. Очень плохой стиль.
Подойдет - программа отожрёт на старте память под весь массив и освободит память при закрытии. Ты не сможешь освободить статически выделенную память во время выполнения.
А вообще - лучше не заморачивайся с глобальными/статическими переменными и выделяй большие массивы на куче. Оверхеды идут тогда, когда ты часто отпускаешь/выделяешь память - а тут у тебя это будет только 1 раз за всё время исполнения. И будет возможность отпустить память до завершения программы.
Сойдёт. Даже более того, пускай будет видно только в пределах main.cpp . Я могу написать в глобальном скоупе
int array[size];
Где будет размещён массив, в стэке или где?
Вот я серьезно не понимаю. Тебе лень прочитать про storage duration на cppreference ссылку же неоднократно вбрасывали в тред или в абсолютно любой книге по C++? Или это дело принципа, чтобы не открывать книгу, а анон тебе все подсказал? Или ты аутист? Или ты тот толстячок, который в конце лета всех доебывал тем, где хранятся объекты? Я не понимаю тебя, блджад, ну вот отвечу я тебе сейчас, у тебя будет новый вопрос, потом еще и еще. Анон не будет тебе вечно разжевывать элементарщину, он заебется и пошлет тебя на хуй. Если у тебя нет элементарных скиллов гугления и одновременно нет усидчивости прочитать блядский учебник Липпмана/Праты/Страуструпа, то нахуя тебе кресты-то вообще? Пиздец какой-то, с кем меня посадили, охуеть, ебаный в рот.
>Тебе лень прочитать про storage duration на cppreference ссылку же неоднократно вбрасывали в тред
Прошёлся ctrl+f по треду, 4 упоминания cppreference -- 2 в корне треда, 1 моё и твоё четвёртое только что. Вот сейчас пятое и шестое опять моё. Про storage duration первый раз слышу.
Мой вопрос на самом деле в том, как вообще канонично делать. И что мне искать на cppreference : сейчас ключевое слово ты мне дал, а как понять самому, что искать?
Нет, я не тот толстячок. Усидчивость есть, нету понимания как делать правильно и почему.
Это в прошлом треде и в позапрошлом было. Платиновый вопрос вообще-то. Алсо, лучше ткни на cppreference раздел Language и прочитай весь материал.
Ну и? ctrl+f storage: единственный результат
http://en.cppreference.com/w/cpp/language/storage_duration
ctrl+f duration: тот же результат
http://en.cppreference.com/w/cpp/language/storage_duration
Перехожу по ссылке. ctrl+f stack ничего не найдено, ctrl+f heap ничего не найдено
BATYA I'm disappointed. Что искать -- дал ты -- понятно, но не найдено.
Это потому что стандарт ничего не гарантирует про стек, про это тоже было в прошлом треде. Фактически на стеке размещается все, что имеет automatic storage duration.
Ну хорошо. Повторяю свои вопросы. Global scope, main.cpp:
int var_1[size];
static int var_2[size];
constexpr int var_3[size];
static constexpr int var_4[size];
1) Где хранится каждая из переменных?
2) Какие у них области видимости?
3) Какое у каждой из них время жизни?
4) Самое главное -- какие ограничения на размер создаваемой памяти (как на стэке или как в куче)?
Попробую сам ответить на свои вопросы:
var_1: не знаю, видна везде, живёт всегда, не знаю
var_2: не знаю, своём файле, живёт всегда, не знаю
var_3: не знаю, видна везде, живёт всегда, не знаю
var_4: не знаю, своём файле, живёт всегда, не знаю
И понятия не имею, где и как выуживать эту информацию.
Во-первых, константы всегда неявно являются static и видны только из своего файла, если ты явно не напишешь extern. Во-вторых, constexpr всегда видна только из своего файла, static, с ней нельзя сделать даже extern, потому что она подставляется при компиляции, в объектных файлах от нее уже ничего не остается. В третьих, с constexpr'ами ты обосрался, так как их необходимо сразу чем-то инициализировать.
Про хранение - они все имеют static storage duration, значит, хранятся в сегменте данных, выделившись один раз перед запуском программы.
Про ограничения - для стека ограничения формирует компилятор, эти ограничения явно указываются в .exe (по сути, компилятор просит выделить на стек одну большую "статическую переменную", которая, тем не менее, имеет фиксированный размер гораздо меньше, чем вся доступная память. Типичен размер в несколько мегабайт, ты можешь его регулировать в параметрах компиляции. Для кучи и статических переменных суммарный размер неограничен, но ОС может отказать в выделении, если ты просишь слишком много и ресурсов системы не хватает.
Ах да, constexpr-переменные вообще не имеют storage duration, они не занимают памяти после компиляции, это просто шаблон для подстановки, наподобие макросов.
>Для кучи и статических переменных суммарный размер неограничен
Вот это я и хотел узнать последние так сообщений сто. Что ж из вас всё клещами-то вытягивать надо.
>>559188
>Ах да, constexpr-переменные вообще не имеют storage duration, они не занимают памяти после компиляции, это просто шаблон для подстановки, наподобие макросов.
Всё не так просто, как ты думаешь.
http://stackoverflow.com/questions/13865842/does-static-constexpr-variable-make-sense
Нет. Речь шла о static в контексте глобальных переменных, а по ссылке речь идет о локальных переменных и членах класса. В этих случаях static имеет разные значения: для локальных переменных оно определяет storage duration, а для глобальных - linkage, ибо глобальные переменные всегда имеют static storage duration. Поэтому применять static к глобальным constexpr-переменным это нонсенс, они и так не могут иметь никакого linkage, кроме internal. А вот к членам класса, например, вполне имеет смысл, т.к. тогда ты сможешь обращаться к ним через ::, не создавая объекты класса. Но все равно, даже для static членов класса не будет сгенерировано никакого кода в рантайме, и не будет выделено никакого места, если они объявлены constexpr. storage duration для constexpr это всего лишь абстракция, показывающая, кто и как имеет право обращаться к ним по имени. Они все равно просто заменятся на конкретные значения во всех точках упоминания при компиляции, никакое static этому не помешает.
Но там речь не о классах, а о скоупе функции. Мне не до конца ясен момент.
И попробую ещё немного вытянуть из тебя клещами по поводу unique_ptr. Вот имеется желанный и вожделенный массив большого заранее известного размера. Некошерно класть его в глобал, поэтому я создам умный указатель.
А как правильно передавать его в функцию? Можно, например, сделать так:
void f(int* arr) {...}
unique_ptr<int> smart_pointer(new int[size]);
f(smart_pointer.get());
Но как-то костыльно...
Если функция не получает владение твоим массивом, то следует передать ей либо const unique_ptr &, либо raw-pointer, как у тебя написано. Если получает - то передавай unique_ptr &&, тогда она сможет удалить массив и все такое прочее.
И еще, если ты пишешь unique_ptr <int>, то твой указатель будет в его деструкторе освобождаться через одиночный delete. Так что при выделении памяти через new [], тебе нужно использовать unique_ptr <int []>, тогда деструктор сделает delete [].
Сап котаны. Был сегодня на собесе на макаку-байтоеба. Немного повредил шаблон. Мне сообщили что при наследовании от 2х несвязанных объектов получается 2 vptr, это блять как?
>И еще, если ты пишешь unique_ptr <int>, то твой указатель будет в его деструкторе освобождаться через одиночный delete. Так что при выделении памяти через new [], тебе нужно использовать unique_ptr <int []>, тогда деструктор сделает delete [].
Спасибо!
>Если функция не получает владение твоим массивом
Да, именно так. Массив пускай помрёт в конце скоупа, где умный указатель.
>то следует передать ей либо const unique_ptr &, либо raw-pointer, как у тебя написано
Как лучше с точек зрения:
1) минимального оверхэда;
2) безопасности, чтобы например не возникло ситуации, когда то, что должно быть уникально, уже не будет таковым, а компилятор в силу сложности проконтролировать возьмёт да скомпилирует?
Откуда стих? Переделка или авторское что-то? В любом случае, спасибо тебе, неизвестный автор, лютейше доставило.
class Mamka;
class Yours;
class YourMomma : public Manka, public Yours {};
Твоя мамка одновременно является объектом класса "Твоя" и класса "Мамка". У каждого из этих классов при наличии виртуальных методов будет vtable. vtable мамки должен подменяться наследником, но если он запихнет в этот подмененный методы "твоей", то возникнет путаница, ибо класс мамки ничего не знает про класс твоей. Очевидное решение - сделать vtable независимыми.
1). Вообще без разницы, в любом случае будет передано 4 байта. Если ты часто будешь получать raw-pointer внутри функции, а доступ к членам unique_ptr например, к deleter'у тебе не нужен, то логично будет передать сразу голый указатель, как у тебя было написано. Или вообще взять * от него и передать ссылку на сам массив (это безопаснее, потому что не придется внутри функции проверять, что аргумент не nullptr, хотя тебе наоборот может понадобиться возможность передать nullptr, это уж от человека зависит).
2). Если ты не будешь удалять raw-указатель самостоятельно или пихать его в новые unique_ptr'ы, то безопасность обеспечивается автоматически. В каждый момент времени только один unique_ptr владеет данными по указателю и может их удалить. Позаботься, чтобы это не произошло до того, как ты перестанешь пользоваться данными, вот и все.
1) Ну если я передаю const unique_ptr & smart_pointer, то к каждому элементу я обращаюсь
smart_pointer.get()[j]
Что назвать оверхэдом, если не вызов .get() каждый раз?
2)
>Если ты не будешь удалять raw-указатель самостоятельно или пихать его в новые unique_ptr'ы, то безопасность обеспечивается автоматически.
Ну т.е. небезопасно. Но я всё равно так буду делать.
3) Ну и, надеюсь, последний вопрос:
>void f(int arr) {...}
Сюда ведь скопируется* адрес или функция будет туда-сюда в smart_pointer.get()[j] бегать? smart_pointer.get() -- аргумент.
fix:
3) Ну и, надеюсь, последний вопрос:
>void f(int* arr) {...}
Сюда ведь скопируется адрес или функция будет туда-сюда в smart_pointer.get()[j] бегать? smart_pointer.get() -- аргумент.
Не, я имею ввиду - это легально, два vptr в одном классе? Про наследование то понятно.
>Похуй на вызов, он инлайнится.
Вот это не факт вообще. Поведение компилятора не определено ничем, кроме компилятора.
Так на каком варианте лучше остановиться, всё-таки? Я ещё раз повторю, что "чтоб работало" сделать я смогу, меня интересует, как делать правильно. А то у меня уже был код, который UB, но почему-то работал как надо, если ничего не путаю.
>Адрес.
Я выделял слово скопируется, т.е. адрес надеюсь не по ссылке будет?
Блять, пока что стер, но смысл был такой, что я читал в vector<char> по размеру в 100 строк, то есть 25*100, потом брал парсил вектор по '\n', потом кидал эти строки в другой вектор уже из строк размером в 100, так как считывал по 100, то каждый раз еще по 100 считывал из второго файла, в итоге получилось что слишком большая сложнасть циклов, что то вроде цикл{цикл{цикл{цикл{сравнение{}}}}}, плюс был еще второй вектор из второго файла, и там еще парс внутри этих циклов по ',' был, в итоге просто все стер, чтобы подумать и заново написать функцию. В память уже сделал, там больше 10к строк вроде он не хочет кушать больше, причем пока с этим тоже немного испоганил, сначала был map, но он удаляет одинаковые, а мне это не надо было, и сделал вектор структур, потом когда с чтением буферизированным парился, сделал вектор пар и там функцию переклипал и структуры эти нахуй удалил. Немного еще подумаю и переделаю. В буст я даже лезть не буду, не хочу даже с ним заморачиваться, он только упрощает жизнь, использовал токенайзер из него чтоб парсить строку, потом сам свой парсер написал. И это совсем даже не лаба, а задание на стажировку было, я проебался, но хочу разобраться. О том что ifstream читает буферезированно я уже понял, читал сегодня на cppreference, и щас я думаю над другим способом, чтобы не был такой большой сложности в алгоритме, знакомый один подсказал, что можно 3 раза прочитать файл, ну тоже небольшие заморочки, но типо должно быть проще.
Согласен, вопрос про работу с указателем по ссылке мог бы и сам нагуглить.
http://www.askdev.ru/c-plus-plus/6460/Разница-между-передачей-указателя-по-ссылке-и-без-ссылки-в-C/
Т.е. по умолчанию указатель копируется, как и переменная, что вполне логично. Сажу себе ставить не буду, тред и так тонет, а сажа прилипчивая.
Вы видите копию треда, сохраненную 4 ноября 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.