Здравствуйте, watchmaker, Вы писали:
W>Здравствуйте, uzhas, Вы писали:
U>>рекомендую обратиться к Стандарту за более точной формулировкой: U>>начни отсюда
W>Да там есть прямым текстом про всю эту ситуацию рассказано:
W>
W>The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not
W>extended; the temporary is destroyed at the end of the full-expression in the return statement.
watchmaker, это ен означает, что при этом константная ссылка становится невалидной
семантика может быть таковой:
— cоздается копия const vector<float>(tmp) к которой и привязывается ссылка. а исходный объект tmp разрушается, как и положено
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, sci_reseacher, Вы писали:
_>>А как можно вернуть ссылку на std::vector<float> в данной ситуации, когда имеется float *? U>зачем вам ссылка нужна? какая задача? возвращайте по значению
U>вот так: U>
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, sci_reseacher, Вы писали:
_>>А как можно вернуть ссылку на std::vector<float> в данной ситуации, когда имеется float *? U>зачем вам ссылка нужна? какая задача? возвращайте по значению
U>вот так: U>
Здравствуйте, sci_reseacher, Вы писали:
_>наверное лучший вариант переделать базовый класс _>
_>struct B {
_> virtual vector<float> getX() = 0 ;
_>};
_>struct C: public B {
_> float *X;
_> int size;
_> virtual vector<float> getX(){
_> vector<float> tmp(X,X+size);
_> return tmp;
_> }
_>};
_>struct D: public B {
_> vector<float> X;
_> virtual vector<float> getX(){
_> return X;
_> }
_>};
_>
_>и использовать так _>
_>const vector<float> & w = d.getX(); // только вот здесь нет ли лишней копии вектора?
_>
тут возможны альтернативы.
нужно оценить, насколько негативно в плане производительности, будет возврат вектора по значению. сколько там элементов ? как часто зовется ?
попробую набросать другие варианты:
1)
struct B {
virtual void getX(vector<float>& result) = 0; <-- при таком подходе можно выиграть на аллокациях, если входной вектор имеет нужный capacity
};
2) оторвать указатель и размер от хранилища, которое владеет памятью
_>P.S. другими словами будет ли метод getX правильно работать? Почему?
Мало того что дико выглядит, так и еще и работать не будет, но это на самом деле к счастью.
Время жизни твоего вектора ограничено временем жизни внутри функции. На что ты хочешь получить ссылку по окончании работы getX? Там же нет ничего, tmp будет гарантированно удален.
Второе замечание, прикинь что твой getX() сидит внутри большого цикла, вместо ожидаемой передачи ссылки на временный буфер, ты каждый раз его будешь строить.
Если тебе нужен временный буфер, то почему его не объявить в struct A?
В основном вектора будут большие, метод getX будет вызываться не часто, планируется использовать только по ссылке возвращаемое значение:
const vector<T> & w = d.getX();
Кроме того, внутри объекта класса решается какого размера вектор и какие значения он будет хранить.
Поэтому остановлюсь на варианте с возвратом вектора vector<T>.
U>тут возможны альтернативы. U>нужно оценить, насколько негативно в плане производительности, будет возврат вектора по значению. сколько там элементов ? как часто зовется ?
Откуда такие сложности на пустом месте, интерфейсы, абстрактные классы, наследования, перегрузка, куча классов, если задача решается напрямую без академических извратов.
Здравствуйте, sci_reseacher, Вы писали:
_>P.S. другими словами будет ли метод getX правильно работать?
Да, он будет правильно работать. Он будет создавать такие проблемы, которые вы будете месяц искать по всей программе.
_>Почему?
Потому что vector состоит из управляющей структуры и массива значений. Управляющую структуру вы создаете на стеке. А это значит, что после выхода из функции, эта память станет свободным местом на стеке и по мере надобности будет переиспользованна, а ее предыдущее содержимое перетерто. Причем произойдет это не сразу, а когда стек дотянется до этого места.
Здравствуйте, peterbes, Вы писали:
P>Здравствуйте, uzhas, Вы писали:
P>Откуда такие сложности на пустом месте, интерфейсы, абстрактные классы, наследования, перегрузка, куча классов, если задача решается напрямую без академических извратов.
в одном классе мне нужен std::vector<T>, в другом T*, т.к. это две разные реализации класса, работающие на разных устройствах --- а пользователь их может выбирать.
удобнее всего вернуть ссылку:
const vector<T>& read(){ ... }
т.к. далее работать с классом проще.
P.S. "академические навороты" нужны чтобы "застолбить" единый интерфейс
Здравствуйте, sci_reseacher, Вы писали:
_>const vector<float> & w = d.getX(); // только вот здесь для D d нет ли лишней копии вектора? всегда работает return value optimization?
У тебя везде делается лишняя копия.
Используй ArrayView. И вместо хранения пары float*, size тоже храни ArrayView.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, sci_reseacher, Вы писали:
_>>const vector<float> & w = d.getX(); // только вот здесь для D d нет ли лишней копии вектора? всегда работает return value optimization?
TB>У тебя везде делается лишняя копия. TB>Используй ArrayView. И вместо хранения пары float*, size тоже храни ArrayView.
а можно по сути разъяснить, как концепция "ArrayView" позволяет не делать лишней копии в указанной ситуации, когда требуется возвращать
TB>>Используй ArrayView. И вместо хранения пары float*, size тоже храни ArrayView.
_>а можно по сути разъяснить, как концепция "ArrayView" позволяет не делать лишней копии в указанной ситуации, когда требуется возвращать _>
_>const std::vector<T> &
_>
Опять же встречный вопрос: «кому требуется»? Концепция view как раз и подразумевает, что больше никому этот вектор не будет нужен, а возвращаться будет сам view. Соответственно, специализированный наследник сможет сам сконструировать view из своих данных (хоть из вектора, хоть из указателя).
То есть использование view позволяет один раз зафиксировать, что невладеющий доступ к массивам или строчкам в программе будет осуществляться через этот тип, а после этого дилеммы об возвращении const vector<int>& уже не возникнет, потому что в нём и не будет надобности.
_>в одном классе мне нужен std::vector<T>, в другом T*, т.к. это две разные реализации класса, работающие на разных устройствах --- а пользователь их может выбирать.
В чём разница, в первом вопросе этого не было, но было копирование.
Да и хрен с ним, а причем тут vector, который у вас возвращался дичайшим никогда невозвратным образом? Тогда берите слайсы над байтовым массивом и работайте напрямую, возвращая клиенту косвенные индексы
_>P.S. "академические навороты" нужны чтобы "застолбить" единый интерфейс
Здравствуйте, sci_reseacher, Вы писали:
_>а можно по сути разъяснить, как концепция "ArrayView" позволяет не делать лишней копии в указанной ситуации, когда требуется возвращать _>
_>const std::vector<T> &
_>
Потому что тебе не нужно возвращать ссылку на вектор. Тебе надо возвращать ArrayView. Тебе же нужно только что? Количество элементов и доступ к элементам. И всё. И этот ArrayView тебе это предоставил. Но надо, конечно, понимать, что время жизни ArrayView должно быть меньше, чем у вектора. Например, возвращать ArrayView на участок вектора, только что созданного на стеке — это очень плохо.
Смысл в том, что ArrayView можно построить на векторе без переголовы, а наоборот — нельзя.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, uzhas, Вы писали:
U>или обратись к Стандарту
Не наш случай. Сей адепт интернет-толкований и научного тыка по компиляторам стандарт не признает.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
_>P.S. другими словами будет ли метод getX правильно работать? Почему?
1) А зачем tmp не временный? Можно же так:
struct A
{
float* X_;
int size;
vector<float> getX(){
return vector<float> tmp(X_,X_+size);
}
_>};
2) Зачем возвращать ссылку? Можно же просто копию, в надежде на RVO, а если объект временным делать нельзя, то NRVO
3) Если С++11 и позже, то возвращаемое значение можно через мув-конструктор получать, что недорого
4) Главное, зачем вообще этот массив float'ов копировать в вектор? Можно же просто возвращать два указателя, в качестве итераторов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском