Как наиболее эффективно (правильно) выполнить передачу (копирование, перемещение ... ) значений из одного вектора x (внутри объекта некоторого класса) в другой вектор y или z, который находиться вне класса в С++11?
class A {
std::vector<int> x;
public:
A(){
x.resize(5,10);
}
const std::vector<int> & f(){
return x ;
}
void g(std::vector<int>::iterator beg){
std::copy(x.begin(),x.end(),beg);
}
};
int main(){
A a;
std::vector<int> y(5);
std::vector<int> z(5);
y = a.f();
a.g(z.begin());
for(auto elem: y) std::cout << elem << " ";
for(auto elem: z) std::cout << elem << " ";
}
Re: как эффективно передать элементы из одного вектора в другой
Хм, вроде же очевидно, что если надо скопировать — то через std::copy, если переместить — то через перемещение. Всё зависит от того, что именно надо.
Если без разницы — то скорее всего передавать ничего не нужно, а нужен доступ к части значений. В этом случае эффективней ограничится просто передачей индексов/итераторов.
Re: как эффективно передать элементы из одного вектора в дру
Здравствуйте, sci_reseacher, Вы писали: _>Уважаемые форумчане! _>Как наиболее эффективно (правильно) выполнить передачу (копирование, перемещение ... ) значений из одного вектора x (внутри объекта некоторого класса) в другой вектор y или z, который находиться вне класса в С++11?
Здравствуйте, sci_reseacher, Вы писали:
_>Как наиболее эффективно (правильно) выполнить передачу (копирование, перемещение ... ) значений из одного вектора x (внутри объекта некоторого класса) в другой вектор y или z, который находиться вне класса в С++11?
Для перемещения — просто и без затей:
std::vector<int> z = std::move(a.x);
Для копирования есть два варианта. Если вектор, в который происходит копирование, уже существует, обладает ненулевым capacity и есть желание эту ёмкость переиспользовать, то можно делать
z.assign(a.x.begin(), a.x.end());
Во всех остальных случаях — просто копируй:
std::vector<int> z = a.x;
Как это всё будет в функции завёрнуто, есть член x хочется сделать недоступным извне класса, — по большом счёту не так уж и важно.
Можно простую обёртку сделать
V data1;
data1.reserve(1000);
A a;
a.CopyTo(data1); // переиспользование выделенного буфера в data1
V data2 = A().CopyX(); // на самом деле не копирование, а перемещение из x
V data3 = a.CopyX(); // а тут честное копирование
Re[2]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, watchmaker, Вы писали:
W>Здравствуйте, sci_reseacher, Вы писали:
_>>Как наиболее эффективно (правильно) выполнить передачу (копирование, перемещение ... ) значений из одного вектора x (внутри объекта некоторого класса) в другой вектор y или z, который находиться вне класса в С++11?
W>Для перемещения — просто и без затей:
W>std::vector<int> z = std::move(a.x);
все-таки вариант SaZ>Я бы юзал std::swap (для перемещения)
более симпатично выглядит (без опасения, что останется x-value)
Re[3]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, _hum_, Вы писали:
__>все-таки вариант SaZ>>Я бы юзал std::swap (для перемещения)
__>более симпатично выглядит (без опасения, что останется x-value)
Что такое x-value, и чем оно не нравится?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re: как эффективно передать элементы из одного вектора в другой
Здравствуйте, sci_reseacher, Вы писали: _>Как наиболее эффективно (правильно) выполнить передачу (копирование, перемещение ... ) значений из одного вектора x (внутри объекта некоторого класса) в другой вектор y или z, который находиться вне класса в С++11?
перемещение —
по-старинке — a.swap(b), по-новому — a = std::move(b)
Re[4]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, _hum_, Вы писали:
__>>все-таки вариант SaZ>>>Я бы юзал std::swap (для перемещения)
__>>более симпатично выглядит (без опасения, что останется x-value)
TB>Что такое x-value, и чем оно не нравится?
— An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue reference is an xvalue. —end example ]
а не нравится именно "an “eXpiring” value". то есть, если я все правильно понимаю, после использования std::move() дальше уже пользоваться объектом не всегда корректно (у него могли забрать ресурсы и сделать инвалидным).
Re[5]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, _hum_, Вы писали:
__>а не нравится именно "an “eXpiring” value". то есть, если я все правильно понимаю, после использования std::move() дальше уже пользоваться объектом не всегда корректно (у него могли забрать ресурсы и сделать инвалидным).
Нет конечно, никто, кроме деструктора, не имеет права делать объект инвалидным.
Объект переходит в нулевое состояние, скорее всего. Для вектора — это пустой вектор. Для классов, у которых нулевого состояния не предусмотрено — облом с крестовым мувом.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[5]: как эффективно передать элементы из одного вектора в другой
__> и сделать инвалидным
Ну нет. Вектор, да и все остальные объекты стандартной библиотеки, гарантированно остается в валидном состоянии после move из него.
__> у него могли забрать ресурсы
А что обратную ситуацию не рассматриваешь?
Вот сделал я явно move из объекта, а он внутри через swap оказался реализован. Тогда swap не забрал ресурсы, лишь обменял. А раз при этом у ресурсов оказался новый владелец, то освободятся они только со смертью этого владельца. Что иногда может произойти ну через очень долгое время. И закиснет где-нибудь в программе указатель на пару гигабайт памяти, на массив дескрипторов GUI-библиотеки или ещё на что-то подобное. Они, конечно, потом освободятся — утечки не будет, но куда лучше будет этот гигабайт памяти сразу освободить как станет ненужным, а не откладывать это действие на конец программы. The Drawbacks of Implementing Move Assignment in Terms of Swap — этот негативный сценарий, конечно, реализуется не слишком часто (и поэтому через swap реализовывать move в общем-то не запрещено), но встречается он всё же чаще, чем невалидный std::vector после перемещения из него.
Re[6]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, _hum_, Вы писали:
__>>а не нравится именно "an “eXpiring” value". то есть, если я все правильно понимаю, после использования std::move() дальше уже пользоваться объектом не всегда корректно (у него могли забрать ресурсы и сделать инвалидным).
TB>Нет конечно, никто, кроме деструктора, не имеет права делать объект инвалидным.
это по правилу хорошего тона? ну, так его не всегда соблюдают. а в общем случае ведь никто не запретит просто забрать данные у x-value способом, делающим объект невалидным для последующих операций.
TB>Объект переходит в нулевое состояние, скорее всего. Для вектора — это пустой вектор. Для классов, у которых нулевого состояния не предусмотрено — облом с крестовым мувом.
ну так для того, чтобы убедиться, что у вектора есть нулевое состояние и оно ничем не грозит, мне нужно лезть куда-то в доки и стандарты, в то время как swap делает это логически прозрачным.
Re[6]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, watchmaker, Вы писали:
W>Здравствуйте, _hum_, Вы писали:
__>> и сделать инвалидным W>Ну нет. Вектор, да и все остальные объекты стандартной библиотеки, гарантированно остается в валидном состоянии после move из него.
еще раз повторюсь, это надо лезть и читать, а что ж там остается от вектора после его std::move другому объекту, и как с этим жить, тогда как swap делает то же смое, при этом не приводя к появлению таких вопросов.
__>> у него могли забрать ресурсы W>А что обратную ситуацию не рассматриваешь? W>Вот сделал я явно move из объекта, а он внутри через swap оказался реализован. Тогда swap не забрал ресурсы, лишь обменял. А раз при этом у ресурсов оказался новый владелец, то освободятся они только со смертью этого владельца.
погодите, речь про swap с пустым вектором. то есть,
Здравствуйте, _hum_, Вы писали:
__>это по правилу хорошего тона? ну, так его не всегда соблюдают. а в общем случае ведь никто не запретит просто забрать данные у x-value способом, делающим объект невалидным для последующих операций.
Бредовый пример. Мне кажется, что это всё равно, как если бы написать в своём контейнере что-то вроде
а потом жаловаться, что range-based-for с таким классом не работает (да ещё и глючит каждый раз по разному), а поэтому range-based-for плохой и использовать его не надо.
А то ведь в стандарте тоже соглашения об смысле методов begin и end — не более чем "правила хорошего тона".
__>ну так для того, чтобы убедиться, что у вектора есть нулевое состояние и оно ничем не грозит, мне нужно лезть куда-то в доки и стандарты, в то время как swap делает это логически прозрачным.
А swap для двух объектов произвольного типа что делает? Неужели обменивает их состояние? Откуда у тебя такая уверенность в этом? Сомневаюсь, что разумный человек может быть в этом уверен без "залезания в доки" или без просмотра исходников. Ведь обменивающее поведение swap — не более чем правило хорошего тона!
Re[7]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, _hum_, Вы писали:
__>погодите, речь про swap с пустым вектором. то есть,
А с непустым что? Никогда не делал присваивания непустому вектору? Вон даже у автора темы в первом сообщении такая строчка есть.
Re[8]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, watchmaker, Вы писали:
W>Здравствуйте, _hum_, Вы писали:
__>>это по правилу хорошего тона? ну, так его не всегда соблюдают. а в общем случае ведь никто не запретит просто забрать данные у x-value способом, делающим объект невалидным для последующих операций.
W>Бредовый пример. Мне кажется, что это всё равно, как если бы написать в своём контейнере что-то вроде
а потом жаловаться, что range-based-for с таким классом не работает (да ещё и глючит каждый раз по разному), а поэтому range-based-for плохой и использовать его не надо. W>А то ведь в стандарте тоже соглашения об смысле методов begin и end — не более чем "правила хорошего тона".
не понял вашу мысль. моя состояла в том, что move-assignement operator/move copy constructor, вообще говоря, не обязаны оставлять переданное им x-value в валидном состоянии (порой очень муторно заводить для объекта "нулевое состояние" и переводить его туда. проще забрать данные и "давай, до свидания"). в конце-концов, в чем тогда выгода вводить eXpired-value, если все равно с ним нужно цацкаться, как с обычным l-value?
__>>ну так для того, чтобы убедиться, что у вектора есть нулевое состояние и оно ничем не грозит, мне нужно лезть куда-то в доки и стандарты, в то время как swap делает это логически прозрачным. W>А swap для двух объектов произвольного типа что делает? Неужели обменивает их состояние? Откуда у тебя такая уверенность в этом? Сомневаюсь, что разумный человек может быть в этом уверен без "залезания в доки" или без просмотра исходников. Ведь обменивающее поведение swap — не более чем правило хорошего тона!
речь шла не о генерализированной функции swap, а о методе. а это значит, никаких вопросов быть не должно — если есть такой метод, значит, есть корректная реализация обмена для векторов.
Re[8]: как эффективно передать элементы из одного вектора в другой
Здравствуйте, watchmaker, Вы писали:
W>Здравствуйте, _hum_, Вы писали:
__>>погодите, речь про swap с пустым вектором. то есть, W>А с непустым что? Никогда не делал присваивания непустому вектору? Вон даже у автора темы в первом сообщении такая строчка есть.
с непустым так делать не нужно, ибо бессмысленно в контексте беседы (переместить объект)
Re[7]: как эффективно передать элементы из одного вектора в
Здравствуйте, _hum_, Вы писали:
__>это по правилу хорошего тона? ну, так его не всегда соблюдают. а в общем случае ведь никто не запретит просто забрать данные у x-value способом, делающим объект невалидным для последующих операций.
Нет, это по правилу, без соблюдения которого класс не считается правильным.
Я не знаю, кто его не соблюдает. Кто-то может и в деструкторе насрать и не убрать, это не значит, что теперь нельзя пользоваться деструкторами.
Подумай сам, если объект после мува невалиден, то как у него будет вызываться деструктор? Ведь компилятору пофиг, делали объекту мув. или нет, он по любому будет его деструктировать.
Так что если увидишь инвалидирующий мув, то пинай этого программиста.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, _hum_, Вы писали:
__>>это по правилу хорошего тона? ну, так его не всегда соблюдают. а в общем случае ведь никто не запретит просто забрать данные у x-value способом, делающим объект невалидным для последующих операций.
TB>Нет, это по правилу, без соблюдения которого класс не считается правильным.
что такое "правильным"?
TB>Я не знаю, кто его не соблюдает. Кто-то может и в деструкторе насрать и не убрать, это не значит, что теперь нельзя пользоваться деструкторами.
не совсем верная аналогия. у деструктора однозначная семантика — завершать существование объекта, а вот у move она расплывчатая (перемещать и оставлять объект только для удаления или все же оставлять его в "нуль состоянии" с возможностью продолжить работу с объектом).
TB>Подумай сам, если объект после мува невалиден, то как у него будет вызываться деструктор? Ведь компилятору пофиг, делали объекту мув. или нет, он по любому будет его деструктировать.
вы наверное не поняли. невалидный не в смысле "даже удалиться не сможет без ошибок",а в смысле — единственное, на что он способен — умереть (на то он и expired). иными словами, он переведен в конечное состояние, из которого нет выхода на нормальную работу (ну, не знаю, например, объект класса, который логически не допускает конструктора по умолчанию, и у которого все нужные для работы данные были перемещены)
TB>Так что если увидишь инвалидирующий мув, то пинай этого программиста.
ну так это и означает, что неинвалидирующий мув — это "по правилу хорошего тона", а значит, нет никаких гарантий
Re[9]: как эффективно передать элементы из одного вектора в
Здравствуйте, _hum_, Вы писали:
__>что такое "правильным"?
Правильным это значит правильным.
__>не совсем верная аналогия. у деструктора однозначная семантика — завершать существование объекта, а вот у move она расплывчатая (перемещать и оставлять объект только для удаления или все же оставлять его в "нуль состоянии" с возможностью продолжить работу с объектом).
TB>>Подумай сам, если объект после мува невалиден, то как у него будет вызываться деструктор? Ведь компилятору пофиг, делали объекту мув. или нет, он по любому будет его деструктировать.
__>вы наверное не поняли. невалидный не в смысле "даже удалиться не сможет без ошибок",а в смысле — единственное, на что он способен — умереть (на то он и expired). иными словами, он переведен в конечное состояние, из которого нет выхода на нормальную работу (ну, не знаю, например, объект класса, который логически не допускает конструктора по умолчанию, и у которого все нужные для работы данные были перемещены)
Это какой-то надуманный класс. Если есть нулевое состояние, то никто не мешает конструировать по умолчанию в него и делать метод вывода из него.
TB>>Так что если увидишь инвалидирующий мув, то пинай этого программиста.
__>ну так это и означает, что неинвалидирующий мув — это "по правилу хорошего тона", а значит, нет никаких гарантий
Насрать в деструкторе — это тоже "правило хорошего тона"? Тебе какое слово нужно, я просто не понимаю? У тебя кодовое слово "мамой клянусь, что всё збс будет"?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: как эффективно передать элементы из одного вектора в другой