Предлагаю в эту тему накидать плюсы, которые вам дало использование c++0x вместо традиционного с++ и грабли, которые он разбросал. Для создания небольшого словарика примеров того, как делать надо и как не надо.
Для нас пока прижилось lambda и auto. Грабли -- пришлось вводить требование на длину лямбы не более 10 строк, ибо если больше, то практически нечитаемо; В GCC есть мелкий баг, что она плохо инстанцирует шаблоны, если параметром его является лямбда (газенбаг), причем лямбду парсит нормально, а остальные аргументы может не разобрать, если они указаны неявно.
<Подпись удалена модератором>
Re: Кто что из c++0x использует. И кто на что нарвался?
enum class
+ удобно — не захламляется пространство имен в котором оно объявлено; ClientResponseType::None порой куда секси и понятнее чем CRT_NONE или ClientResponseType_None
— пока ещё непривычно и порой возникают wtf при чтении; VC++ 2010 не поддерживает, IntelliSense не поддерживает
nullptr
+ приятно — по сравнению с NULL, при чтении, я сразу стал понимать что тут делается + проверка времени компиляции
— только последние ICC и GCC держат его
override
+ обалденно — то, что должно ещё быть в С++ 99 — проверка времени компиляции; читаемость++
— нет полной поддержки
&&
+ оргазм — теперь у меня по одной паре аллокация/освобождение, AddRef()/Release() вместо нескольких; производительность++
— надо уметь готовить, больше писать
auto + decltype
классно (без комментариев)
Re: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, denisko, Вы писали:
D>Предлагаю в эту тему накидать плюсы, которые вам дало использование c++0x вместо традиционного с++ и грабли, которые он разбросал.
Прижились и сильно облегчили жизнь:
auto
decltype
variadic templates
defaulted and deleted functions
rvalue references
concatenation of mixed-width string literals
static_assert
ну и мелочи там всякие типа >>, trailing comma и др.
лямбды так и не нашёл куда приткнуть чтоб с ними было лучше чем без них.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[2]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, о_О, Вы писали:
о_О>&& о_О>+ оргазм — теперь у меня по одной паре аллокация/освобождение, AddRef()/Release() вместо нескольких; производительность++ о_О>- надо уметь готовить, больше писать
А можно по-подробнее, а то я уже много чего из нового стандарта использую, но профита от && никак не могу понять.
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, о_О, Вы писали:
о_О>>&& о_О>>+ оргазм — теперь у меня по одной паре аллокация/освобождение, AddRef()/Release() вместо нескольких; производительность++ о_О>>- надо уметь готовить, больше писать AD>А можно по-подробнее, а то я уже много чего из нового стандарта использую, но профита от && никак не могу понять.
код становится гораздо проще.
Можно все возвращать по значению, не опасаясь за производительность.
Здравствуйте, ArtDenis, Вы писали:
о_О>>&& о_О>>+ оргазм — теперь у меня по одной паре аллокация/освобождение, AddRef()/Release() вместо нескольких; производительность++ о_О>>- надо уметь готовить, больше писать AD>А можно по-подробнее, а то я уже много чего из нового стандарта использую, но профита от && никак не могу понять.
Эту штуку используют для перемещения состояний между объектами. Надеюсь я правильно выразился.
Например, через push_back(value_type&& x) можно засунуть данные объекта в контейнер без лишнего копирования. Фактически вместо копирования работают swap-алгоритмы.
Поскольку пока все еще хочу сохранять совместимость исходного кода со "старыми" компиляторами. Типа VS2005/VS2008. Хотя сейчас 99% провожу в VS2010
----
Вот что бы я очень хотел бы юзать так это auto. Бо (накатав достаточно много кода на C# с его var) явное указание типов для переменных уже напрягает.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Кто что из c++0x использует. И кто на что нарвался?
КД>Можно вместо "return result;" написать "return std::move(result);" и ты будешь "перемещать" result в результат функции, а не копировать его.
имхо это пример, как неправильно использовать move
return result; <-- достаточно без всяких move
компилятор сообразит, что лучше сделать
это все равно, что советовать кругом вставлять слово inline
Re[5]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>имхо это пример, как неправильно использовать move U>return result; <-- достаточно без всяких move U>компилятор сообразит, что лучше сделать U>это все равно, что советовать кругом вставлять слово inline
Возможно, но я по-моему тестировал — компилятор VS2010 не рюхал и ему надо было подсказывать
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, denisko, Вы писали:
D>Предлагаю в эту тему накидать плюсы, которые вам дало использование c++0x вместо традиционного с++ и грабли, которые он разбросал. Для создания небольшого словарика примеров того, как делать надо и как не надо.
используем &&
грабли в &&
1) люди начинают их впихивать туда, где передача по значению была бы приемлемой (тут можете меня поучить)
пример:
//class B is movableclass A
{
public:
//я чего-то не понимаю или тут реально не нужно && ? ведь это ненужное ограничение на клиентаvoid SetB(B&& b)
{
m_b = std::move(b);
}
B m_b;
};
2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator= (тут тоже можете меня поучить)
Здравствуйте, uzhas, Вы писали:
U>грабли в && U>1) люди начинают их впихивать туда, где передача по значению была бы приемлемой (тут можете меня поучить) U>пример:
//class B is movableclass A
{
public:
//я чего-то не понимаю или тут реально не нужно && ? ведь это ненужное ограничение на клиентаvoid SetB(B&& b)
{
m_b = std::move(b);
}
B m_b;
};
Лично я определяю SetB(B&& b) только в довесок к нормальному "void SetB(const B& b)"
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Лично я определяю SetB(B&& b) только в довесок к нормальному "void SetB(const B& b)"
а для чего это надо? почему нельзя было обойтись одним методом, принимающим аргумент по значению?
void SetB(B b);
я могу себе еще такое представить, когда два метода определяются в шаблонных классах, ибо они могут работать как с movable, так и не с movable классами (хотя тут тоже есть о чем кумекать)
Re[4]: Кто что из c++0x использует. И кто на что нарвался?
КД>Можно вместо "return result;" написать "return std::move(result);" и ты будешь "перемещать" result в результат функции, а не копировать его.
Такая замена только исключит возможность применения RVO. В отношении return действуют особые правила:
12.8/32:
When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload resolution fails, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. —end note ]
[ Example:
class Thing {
public:
Thing();
~Thing();
Thing(Thing&&);
private:
Thing(const Thing&);
};
Thing f(bool b) {
Thing t;
if (b)
throw t; // OK: Thing(Thing&&) used (or elided) to throw treturn t; // OK: Thing(Thing&&) used (or elided) to return t
}
Thing t2 = f(false); // OK: Thing(Thing&&) used (or elided) to construct t2
—end example ]
Re[4]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
КД>>Лично я определяю SetB(B&& b) только в довесок к нормальному "void SetB(const B& b)" U>а для чего это надо? почему нельзя было обойтись одним методом, принимающим аргумент по значению? U>void SetB(B b);
Я хотел написать, что "только с появлением && стал понятен очень древний совет — передавать аргументы по значению. типа компилятор там сам разберется". Но потом передумал
Да потому что если код будет собираться старым компилятором, то
void SetB(B b)
{
m_std_vector_of_B.push_back(b);
}
будет хуже чем
void SetB(const B& b)
{
m_std_vector_of_B.push_back(b);
}
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[5]: Кто что из c++0x использует. И кто на что нарвался?
КД>Я хотел написать, что "только с появлением && стал понятен очень древний совет — передавать аргументы по значению. типа компилятор там сам разберется". Но потом передумал
это свежий совет
древний совет — передавайте все по ссылке
хочется разобраться когда применять свежий совет, а когда нет
КД>Да потому что если код будет собираться старым компилятором, то
все же меня интересуют именно новые возможности, хочется в них разобраться
Re[6]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>>Я хотел написать, что "только с появлением && стал понятен очень древний совет — передавать аргументы по значению. типа компилятор там сам разберется". Но потом передумал U>это свежий совет U>древний совет — передавайте все по ссылке U>хочется разобраться когда применять свежий совет, а когда нет
Атомарные данные — по значению. Агрегаты — по ссылке.
Типа Капитан Очевидность.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[7]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, LaptevVV, Вы писали:
LVV>Атомарные данные — по значению. Агрегаты — по ссылке. LVV>Типа Капитан Очевидность.
больше похоже на Капитан Невтеме
Re[2]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>грабли в && U>1) люди начинают их впихивать туда, где передача по значению была бы приемлемой U>2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator= (тут тоже можете меня поучить)
это потому что люди не умеют готовить &&. в частности не понимают разницы std::forward/std::move и как их использовать, и вообще "что там происходит"
Здравствуйте, о_О, Вы писали:
о_О>это потому что люди не умеют готовить &&. в частности не понимают разницы std::forward/std::move и как их использовать, и вообще "что там происходит"
научите готовить
более-менее конкретные примеры я описал выше, как по-вашему "правильно" их написать?
Re[3]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>>Лично я определяю SetB(B&& b) только в довесок к нормальному "void SetB(const B& b)" U>а для чего это надо? почему нельзя было обойтись одним методом, принимающим аргумент по значению? U>void SetB(B b); U>я могу себе еще такое представить, когда два метода определяются в шаблонных классах, ибо они могут работать как с movable, так и не с movable классами (хотя тут тоже есть о чем кумекать)
Потому что представь, что твой В — это тяжелый std::vector.
Здравствуйте, jazzer, Вы писали:
J>Потому что представь, что твой В — это тяжелый std::vector.
ну прямо под землю провалимся от его веса
если клиент захочет отдать объект, он передаст владение через вызов SetB(std::move(b));
если не захочет — то передаст копию SetB(b);
Re[4]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>научите готовить
сомневаюсь что моё дилетантское мнение кому-то интересно, но тем не менее:
U>1) люди начинают их впихивать туда, где передача по значению была бы приемлемой (тут можете меня поучить)
class A
{
public:
//я чего-то не понимаю или тут реально не нужно && ? ведь это ненужное ограничение на клиентаvoid SetB(B&& b)
{
m_b = std::move(b);
}
B m_b;
};
т.к. && обладают другой семантикой по сравнению с обычными &, использовать && вместо чего-то не нужно. && нужно дополнять к уже имеющимся методам. что касается случая с передачей по значению, то тут лучше вообще не использовать ни замещение ни дополнение:
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, jazzer, Вы писали:
J>>Потому что представь, что твой В — это тяжелый std::vector. U>ну прямо под землю провалимся от его веса U>если клиент захочет отдать объект, он передаст владение через вызов SetB(std::move(b)); U>если не захочет — то передаст копию SetB(b);
Ну да, либо ты делаешь все на вызывающей стороне, либо на вызваемой
Обычно предпочитают делать на вызываемой, чтоб облегчить клиентский код, чтоб клиенту не надо было все время писать std::move (более того, тебе его тоже придется написать, когда будешь присваивать).
Здравствуйте, о_О, Вы писали:
о_О>т.к. && обладают другой семантикой по сравнению с обычными &, использовать && вместо чего-то не нужно. && нужно дополнять к уже имеющимся методам.
возможно, вас сбило слово "впихивать", поэтому вы подсчитали, что что-то наращивается
представим, что класс A пишется с нуля
какую сигнатуру для SetB вы порекомендуете?
U>>2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator=
о_О>т.к. мы можем принять временный объект, а можем переместить один объект в другой, реализация A::operator=(B&& b) должна быть следующей: о_О>
о_О> - освобождение ресурсов A
о_О> - перемещение ресурсов B в A
о_О>
о_О>а вот как вы это реализуете, уже не имеет значения. смысл лишь в том, чтобы объект A был чист перед перемещением, а объект B после перемещения.
ваше мнение понятно и оно вполне логично, только не у всех оно укладывается в голове (в частности у меня )
из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3
если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще
если бы std::move не превращал нормальные объекты во "временные", то можно было бы делать банальный swap (variant 2), а так как новый стандарт разрешает корежить\портить нормальные объекты, то приходится изголяться, как в variant 3, что неблаготворно сказывается на качестве кода
Re[7]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, jazzer, Вы писали:
J>Ну да, либо ты делаешь все на вызывающей стороне, либо на вызваемой
казалось бы палка о двух концах, но я так не считаю
напомню о чем я говорю, чтобы мы говорили об одном и том же:
SetB(B&&) с точки зрения дизайна вносит необоснованное ограничение (невозможность подставить lvalue) ради некоторой оптимизации
SetB(B b) не имеет такого ограничения и тоже позволяет применить оптимизацию
так вот:
1) не все вектора тяжелые
2) класс чаще всего может работать как я тяжелыми так и с легкими векторами, как следствие, решение тяжелый вектор или нет вполне логично принять на клиентской стороне
3) нет такой best-practice передавать владения векторов, вектор как тип нетяжелый, тяжелым он может быть лишь в некоторых случаях в рантайме
J>Обычно предпочитают делать на вызываемой, чтоб облегчить клиентский код, чтоб клиенту не надо было все время писать std::move (более того, тебе его тоже придется написать, когда будешь присваивать).
в реальности облегчения скорее всего не будет, т.к. клиенту все равно надо будет писать std::move, если у него lvalue
весь вопрос в том, должен ли его заставить это сделать метод SetB или же предоставить клиенту выбор
если выбора нет, то передать копию клиенту придется так:
B b;
SetB(B(b));
//work with b
Re[6]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, о_О, Вы писали:
о_О>>т.к. && обладают другой семантикой по сравнению с обычными &, использовать && вместо чего-то не нужно. && нужно дополнять к уже имеющимся методам. U>возможно, вас сбило слово "впихивать", поэтому вы подсчитали, что что-то наращивается U>представим, что класс A пишется с нуля U>какую сигнатуру для SetB вы порекомендуете?
по значению
U>>>2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator=
о_О>>т.к. мы можем принять временный объект, а можем переместить один объект в другой, реализация A::operator=(B&& b) должна быть следующей: о_О>>
о_О>> - освобождение ресурсов A
о_О>> - перемещение ресурсов B в A
о_О>>
о_О>>а вот как вы это реализуете, уже не имеет значения. смысл лишь в том, чтобы объект A был чист перед перемещением, а объект B после перемещения. U>ваше мнение понятно и оно вполне логично, только не у всех оно укладывается в голове (в частности у меня )
почему?)
U>из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3
вариант 2 вообще неверен, остались 1 и 3.
U>если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще
у GCC вариант 1
U>если бы std::move не превращал нормальные объекты во "временные", то можно было бы делать банальный swap (variant 2), а так как новый стандарт разрешает корежить\портить нормальные объекты, то приходится изголяться, как в variant 3, что неблаготворно сказывается на качестве кода
для простых типов возможен только вариант 1. итого 2 разные реализации == ни есть гут
и вообще. у vc++ 3й, у gcc 1й; у меня, 1й у вас 3й -- быдлан какой-то
Re[7]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, о_О, Вы писали:
U>>какую сигнатуру для SetB вы порекомендуете?
о_О>по значению
вот и у меня такое же мнение
U>>ваше мнение понятно и оно вполне логично, только не у всех оно укладывается в голове (в частности у меня )
о_О>почему?)
да напрягает как-то освобождать сви ресурсы
вместо того, чтобы всю деструктивную логику держать в деструкторе, мне приходится делать функцию CloseAll() и вызывать ее из деструктора и из operator=(A&&) U>>из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3
о_О>вариант 2 вообще неверен, остались 1 и 3.
виноват, забыл return, основная идея этого варианта в банальном swap-е
U>>если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще
о_О>у GCC вариант 1
опачки, это интересно
о_О>и вообще. у vc++ 3й, у gcc 1й; у меня, 1й у вас 3й -- быдлан какой-то
я был бы рад, если бы вариант 2 был приемлем )) уж очень он простой )))
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, о_О, Вы писали:
U>>>какую сигнатуру для SetB вы порекомендуете?
о_О>>по значению
U>вот и у меня такое же мнение
всё верно. и вы уже сами объяснили почему
U>>>из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3 о_О>>вариант 2 вообще неверен, остались 1 и 3. U>виноват, забыл return, основная идея этого варианта в банальном swap-е
я и не заметил про return
я когда в свой умный указатель для COM объедков прикручивал && вначале так и написал — swap(). потом подумал и понял, что fail. далее я долго маялся — как же делать — вариант 1 или 3. т.к. я помешан на читаемости кода, решил что 1
U>>>если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще
о_О>>у GCC вариант 1 U>опачки, это интересно
stl в vs 2010 кривая. вон у shared_ptr нельзя явно инстанцировать экземпляр, т.к. они вместо _Swap написали swap
вот тут если не ошибаюсь:
Здравствуйте, Masterkent, Вы писали:
M>Ну и неплохо было бы напомнить о существовании 4-го варианта:
M>
A &operator=(A &&) noexcept = default;
M>Добиться, чтобы это сработало, во многих случаях не так уж и сложно. Заодно не нужно будет думать о реализации функции swap (std::swap вполне хватит).
каюсь, про defaulted, deleted ещё не читал
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Masterkent, Вы писали:
M>о_О:
о_О>>вариант 2 вообще неверен, остались 1 и 3.
M>Вариант 2 вполне может быть верным, тут всё зависит от требований к состоянию moved from объекта в каждом конкретном случае.
M>Ну и неплохо было бы напомнить о существовании 4-го варианта:
M>
A &operator=(A &&) noexcept = default;
M>Добиться, чтобы это сработало, во многих случаях не так уж и сложно. Заодно не нужно будет думать о реализации функции swap (std::swap вполне хватит).
можно у вас, как эксперта приближенного к процессу стандартизации, спросить ссылок на то какую проблему эта вся синтаксическая карусель с rvalue решила? То есть хочется понять на примере "проблема-решение" что все эти закорючки значат. Можно просто ссылки на код, можно на группы/обсуждения. Хоть что нибудь, пожалуйста.
зы я обеими ногами за #include <thread> и все что с ним связано, но пока выглядит этот новый язык как мутный головняк.
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, SleepyDrago, Вы писали:
SD>можно у вас, как эксперта приближенного к процессу стандартизации, спросить ссылок на то какую проблему эта вся синтаксическая карусель с rvalue решила? То есть хочется понять на примере "проблема-решение" что все эти закорючки значат. Можно просто ссылки на код, можно на группы/обсуждения. Хоть что нибудь, пожалуйста.
Да вот хотя бы примитивный тест:
1М элементов
sort для vector<string> — 1.852954 sec, дофигища копирований
sort для vector<string>, string c поддержкой move constructor/operator — 0.532721 sec, ни одного копирования
Разница в 3.478280 раза
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, SleepyDrago, Вы писали:
SD>можно у вас, как эксперта приближенного к процессу стандартизации, спросить ссылок на то какую проблему эта вся синтаксическая карусель с rvalue решила? То есть хочется понять на примере "проблема-решение" что все эти закорючки значат.
Там все просто.
В С++03 при присваивании или инициализации из временного объекта происходит сначала копирование всего содержимого объекта в новый, а потом разрушение временного. std::vector, например — нужно выделить память, скопировать все объекты, которые можуг быть тяжелыми сами по себе, хотя достаточно было всего лишь перекинуть указатель на буфер и обойтись вообще без выделений и копирований.
В С++11 ссылки на rvalue позволяют явно прописать, как именно перемещать содержимое из временного объекта, и компилятор будет этим способом по возможности пользоваться.
Здравствуйте, Banned by IT, Вы писали:
BBI>1М элементов BBI>sort для vector<string> — 1.852954 sec, дофигища копирований BBI>sort для vector<string>, string c поддержкой move constructor/operator — 0.532721 sec, ни одного копирования BBI>Разница в 3.478280 раза
Я может че не понимаю... Если нужна производительность сортировки массива, то
1) можно хранить указатели на объекты (в данном случае строк).
2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, jazzer, Вы писали:
J>>Ну да, либо ты делаешь все на вызывающей стороне, либо на вызваемой U>казалось бы палка о двух концах, но я так не считаю U>напомню о чем я говорю, чтобы мы говорили об одном и том же: U>SetB(B&&) с точки зрения дизайна вносит необоснованное ограничение (невозможность подставить lvalue) ради некоторой оптимизации U>SetB(B b) не имеет такого ограничения и тоже позволяет применить оптимизацию
Это ложный выбор. Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.
Здравствуйте, Banned by IT, Вы писали:
BBI>variadic templates
а можно примеров их удобного использования? пока встречал только всякую плохочитабельную содомию..
хотя у меня был ровно один случай, где они бы пригодились..
...coding for chaos...
Re[3]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, neFormal, Вы писали:
BBI>>variadic templates
F>а можно примеров их удобного использования? пока встречал только всякую плохочитабельную содомию.. F>хотя у меня был ровно один случай, где они бы пригодились..
У меня тоже ровно один случай: typesafe аналог CString::Format. Раньше там была уличная магия через operator comma.
Вариадики — штука специфическая, реальная необходимость в них есть только вот таких вот случаях: когда надо передать в функцию неизвестное колво параметров и разных типов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Sir-G, Вы писали:
BBI>>1М элементов BBI>>sort для vector<string> — 1.852954 sec, дофигища копирований BBI>>sort для vector<string>, string c поддержкой move constructor/operator — 0.532721 sec, ни одного копирования BBI>>Разница в 3.478280 раза SG>Я может че не понимаю... Если нужна производительность сортировки массива, то
Это всего лишь был наглядный пример. Есеснно этого достичь можно разными путями. Но && введено в стандарт именно для уменьшения объёмов рукопашки.
Кроме сортировки также просто ускоряется к примеру всякий container.push_back (Object (param, param, ...)); и прочие места где объект обычно передаётся как rvalue.
SG>1) можно хранить указатели на объекты (в данном случае строк).
Можно. Но с && можно хранить сами объекты, что сильно удобнее в использовании, и тем не менее тот же vector resize будет происходить в разы быстрее.
SG>2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.
Можно. Но тогда надо переписать тонну стандартных алгоритмов чтоб они умели использовать специальный swap для твоего типа и стандартный swap для всех остальных?
А так у тебя есть где то в глубине:
template <class T> std::move (T& a, T& b)
{
T c = std::move (a);
a = std::move (b);
b = std::move (c);
}
Который в зависимости от того имеет класс move constructor/operator= или нет работает либо через copy либо через move. Сам, автоматически.
В этом и есть смысл.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Sir-G, Вы писали:
SG>Я может че не понимаю... Если нужна производительность сортировки массива, то SG>1) можно хранить указатели на объекты (в данном случае строк). SG>2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.
STL из VS2010 при перепаковке вектора использует swap, а тот использует move-операции.
Так что лучше сразу определить свой вариант swap.
Если я все правильно попутал
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
J>Это ложный выбор. Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.
Ну setB — ладно. А предположим есть функция с тремя аргументами — это что, 8 перегрузок получается?
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, jazzer, Вы писали:
J>Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.
чем это лучше одного метода SetB(B b) ?
я вижу лишь усложнение, а где же профит? экономия на стеке?
Re[10]: Кто что из c++0x использует. И кто на что нарвался?
uzhas:
J>>Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий. U>чем это лучше одного метода SetB(B b) ? U>я вижу лишь усложнение, а где же профит? экономия на стеке?
Если имеется в виду сравнение
class A
{
public:
void SetB(B const &b)
{
m_b = b;
}
void SetB(B &&b)
{
m_b = std::move(b);
}
// ...private:
B m_b;
};
с
class A
{
public:
void SetB(B b)
{
m_b = std::move(b);
}
// ...private:
B m_b;
};
то во втором варианте получается на одну move-операцию больше (в некоторых случаях она быть устранена в соответствии с 12.8/31/3). Если такая дополнительная move-операция не напрягает, то передача по значению сгодится. Напомню, что перемещение не всегда дешёвое — нередко оно сводится к копированию.
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Masterkent, Вы писали:
M>Если имеется в виду сравнение
да, речь об этих вариантах
но мы немного уже запутали друг друга))
моя позиция следующая
//class B is movableclass A1
{
B m_b;
public:
void SetB(B b)
{
m_b = std::move(b);
}
};
class A2
{
B m_b;
public:
void SetB(const B& b)
{
m_b = b;
}
void SetB(B&& b)
{
m_b = std::move(b);
}
};
class A3
{
B m_b;
public:
void SetB(B&& b)
{
m_b = std::move(b);
}
};
из предложенных трех вариантов на практике с точки зрения дизайна в подавляющем кол-ве случаев самым лучшим является вариант A1:
в A2 я вижу дубликацию логики (профит может быть в слишком специфических случаях, когда двойной move в A1 плохо сказывается на перформансе)
в A3 я вижу необоснованное ограничение "отдай мне владение", об этом я писал выше
то есть передавайте по значению — это хорошее полезное правило для легко movable сущностей, что-то типа best practice
Re[12]: Кто что из c++0x использует. И кто на что нарвался?
Вот же ж склероз — в который раз уже забыл noexcept у move-операций проставить.
struct B
{
// ...
B(B const &x);
B(B &&x) noexcept; // или хотя бы throw()
B &operator =(B const &x)
{
return *this = B(x);
}
B &operator =(B &&x) noexcept; // или хотя бы throw()
};