Re[12]: ссылка на локальный вектор
От: uzhas Ниоткуда  
Дата: 16.05.16 11:26
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Да там есть прямым текстом про всю эту ситуацию рассказано:


точно, не доскролил туда
хотя это не про наш случай, ведь у нас нет temporary
Отредактировано 16.05.2016 11:31 uzhas . Предыдущая версия . Еще …
Отредактировано 16.05.2016 11:28 uzhas . Предыдущая версия .
Re[12]: ссылка на локальный вектор
От: _hum_ Беларусь  
Дата: 16.05.16 11:27
Оценка:
Здравствуйте, 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 разрушается, как и положено
Re[13]: ссылка на локальный вектор
От: watchmaker  
Дата: 16.05.16 11:30
Оценка:
Здравствуйте, uzhas, Вы писали:

U>хотя это не про наш слцчай, ведь у нас нет temporary


Так дело в том, что если бы он и был, то это всё равно бы не помогло
Re[14]: ссылка на локальный вектор
От: uzhas Ниоткуда  
Дата: 16.05.16 11:33
Оценка: :)
Здравствуйте, watchmaker, Вы писали:

W>Так дело в том, что если бы он и был, то это всё равно бы не помогло


не запутывай нераспутываемое!
Re[4]: ссылка на локальный вектор
От: Current  
Дата: 16.05.16 12:04
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, sci_reseacher, Вы писали:



_>>А как можно вернуть ссылку на std::vector<float> в данной ситуации, когда имеется float *?

U>зачем вам ссылка нужна? какая задача? возвращайте по значению

U>вот так:

U>
U>vector<float> getVector(){
U>  vector<float> tmp(X_,X_+size);
U>  return tmp;
U>}

U>vector<float> a1 = getVector(); // <-- valid
U>const vector<float>& a2 = getVector(); // <-- valid as well
U>



сколько раз здесь будет копирование объекта?
Re[4]: ссылка на локальный вектор
От: sci_reseacher  
Дата: 16.05.16 12:40
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, sci_reseacher, Вы писали:



_>>А как можно вернуть ссылку на std::vector<float> в данной ситуации, когда имеется float *?

U>зачем вам ссылка нужна? какая задача? возвращайте по значению

U>вот так:

U>
U>vector<float> getVector(){
U>  vector<float> tmp(X_,X_+size);
U>  return tmp;
U>}

U>vector<float> a1 = getVector(); // <-- valid
U>const vector<float>& a2 = getVector(); // <-- valid as well
U>


нужно сделать наследников D и C класса B, таких, что в одном данные хранятся в std::vector<T>, а в другом классе T* указывает на эти данные.

struct B {
    virtual const vector<float> &  getX() = 0 ;
};


struct C: public B {
    float *X;
    int size;
//    vector<float>  getX(){
//    vector<float> tmp(X,X+size);
//    return tmp;
//    }
};

struct D: public B {
    vector<float> X;
    const vector<float>  & getX(){
        return X;
    }
};


наверное лучший вариант переделать базовый класс

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(); // только вот здесь для D d нет ли лишней копии вектора? всегда работает return value optimization?
Отредактировано 16.05.2016 12:58 sci_reseacher . Предыдущая версия . Еще …
Отредактировано 16.05.2016 12:56 sci_reseacher . Предыдущая версия .
Отредактировано 16.05.2016 12:54 sci_reseacher . Предыдущая версия .
Отредактировано 16.05.2016 12:41 sci_reseacher . Предыдущая версия .
Re[15]: ссылка на локальный вектор
От: uzhas Ниоткуда  
Дата: 16.05.16 12:50
Оценка:
Здравствуйте, uzhas, Вы писали:

U>не запутывай нераспутываемое!


кстати, еще один нюанс : http://rsdn.ru/forum/cpp/5797699.1
Автор: uzhas
Дата: 26.09.14
Re[5]: ссылка на локальный вектор
От: uzhas Ниоткуда  
Дата: 16.05.16 13:08
Оценка: 1 (1)
Здравствуйте, 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) оторвать указатель и размер от хранилища, которое владеет памятью
struct B {
  virtual float* getXBegin() = 0;
  virtual size_t getXSize() = 0;
};


3) можно объединить размер и указатель
struct B {
  virtual pair<float*, size_t> getX() = 0;
};


4) либо сделать\заюзать аналог array_view/string_view/string_ref/ link: http://stackoverflow.com/questions/34832090/whats-the-difference-between-span-and-array-view-in-the-gsl-library

5) либо прокинуть функтор для итерации по контейнеру (поэлементно, либо некими группами\страницами)
struct B {
  virtual void processX(std::function<float> f) = 0; //<-- f will be invoked for each "float" value
};


успехов
Re: ссылка на локальный вектор
От: peterbes Россия  
Дата: 16.05.16 13:52
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>Можно ли передавать ссылку на вектор, созданный локально?

_>
_>struct A
_>{
_>    float* X_;
_>    int size;
_>    const vector<float> & getX(){
_>        vector<float> tmp(X_,X_+size);
_>        return tmp;
_>    }
    
_>};
_>

_>P.S. другими словами будет ли метод getX правильно работать? Почему?

Мало того что дико выглядит, так и еще и работать не будет, но это на самом деле к счастью.
Время жизни твоего вектора ограничено временем жизни внутри функции. На что ты хочешь получить ссылку по окончании работы getX? Там же нет ничего, tmp будет гарантированно удален.
Второе замечание, прикинь что твой getX() сидит внутри большого цикла, вместо ожидаемой передачи ссылки на временный буфер, ты каждый раз его будешь строить.
Если тебе нужен временный буфер, то почему его не объявить в struct A?
Re[6]: ссылка на локальный вектор
От: sci_reseacher  
Дата: 16.05.16 14:34
Оценка:
Здравствуйте, uzhas, Вы писали:


В основном вектора будут большие, метод getX будет вызываться не часто, планируется использовать только по ссылке возвращаемое значение:
const vector<T> & w = d.getX();
Кроме того, внутри объекта класса решается какого размера вектор и какие значения он будет хранить.

Поэтому остановлюсь на варианте с возвратом вектора vector<T>.

U>тут возможны альтернативы.

U>нужно оценить, насколько негативно в плане производительности, будет возврат вектора по значению. сколько там элементов ? как часто зовется ?
Re[6]: ссылка на локальный вектор
От: peterbes Россия  
Дата: 16.05.16 15:35
Оценка:
Здравствуйте, uzhas, Вы писали:

Откуда такие сложности на пустом месте, интерфейсы, абстрактные классы, наследования, перегрузка, куча классов, если задача решается напрямую без академических извратов.


 template<class T>
 struct AB
 {
 public:
   AB(){}
   void write( const size_t size, T* pT )
   {
     if (_data.size() < size)_data.resize( size );
     copy( pT, pT + size, _data.begin() );
   }

   const vector<T>& read(){ return _data; }
   size_t get_size(){ return _data.size(); }
 private:
   vector<T> _data;

 };


  float mydata[] = { 1.0f, 2.4f, 3.14f, 2.71f };
  AB<float> sci_buf;
  //sci_buf.w
  sci_buf.write( 4, (float*) mydata );
  auto& Vals = sci_buf.read(); 
 
  Vals[2] = 2.53f; <---- Хлоп! Ошибка компиляции, данные только на чтение
Re: ссылка на локальный вектор
От: Pzz Россия https://github.com/alexpevzner
Дата: 16.05.16 15:38
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>P.S. другими словами будет ли метод getX правильно работать?


Да, он будет правильно работать. Он будет создавать такие проблемы, которые вы будете месяц искать по всей программе.

_>Почему?


Потому что vector состоит из управляющей структуры и массива значений. Управляющую структуру вы создаете на стеке. А это значит, что после выхода из функции, эта память станет свободным местом на стеке и по мере надобности будет переиспользованна, а ее предыдущее содержимое перетерто. Причем произойдет это не сразу, а когда стек дотянется до этого места.
Re[7]: ссылка на локальный вектор
От: sci_reseacher  
Дата: 16.05.16 16:41
Оценка:
Здравствуйте, peterbes, Вы писали:

P>Здравствуйте, uzhas, Вы писали:


P>Откуда такие сложности на пустом месте, интерфейсы, абстрактные классы, наследования, перегрузка, куча классов, если задача решается напрямую без академических извратов.



P>
P> template<class T>
P> struct AB
P> {
P> public:
P>   AB(){}
P>   void write( const size_t size, T* pT )
P>   {
P>     if (_data.size() < size)_data.resize( size );
P>     copy( pT, pT + size, _data.begin() );
P>   }

P>   const vector<T>& read(){ return _data; }
P>   size_t get_size(){ return _data.size(); }
P> private:
P>   vector<T> _data;

P> };
P>


P>
P>  float mydata[] = { 1.0f, 2.4f, 3.14f, 2.71f };
P>  AB<float> sci_buf;
P>  //sci_buf.w
P>  sci_buf.write( 4, (float*) mydata );
P>  auto& Vals = sci_buf.read(); 
 
P>  Vals[2] = 2.53f; <---- Хлоп! Ошибка компиляции, данные только на чтение
P>



в одном классе мне нужен std::vector<T>, в другом T*, т.к. это две разные реализации класса, работающие на разных устройствах --- а пользователь их может выбирать.

удобнее всего вернуть ссылку:
const vector<T>& read(){ ... }

т.к. далее работать с классом проще.

P.S. "академические навороты" нужны чтобы "застолбить" единый интерфейс
Отредактировано 16.05.2016 16:42 sci_reseacher . Предыдущая версия .
Re[5]: ссылка на локальный вектор
От: T4r4sB Россия  
Дата: 16.05.16 16:59
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>const vector<float> & w = d.getX(); // только вот здесь для D d нет ли лишней копии вектора? всегда работает return value optimization?


У тебя везде делается лишняя копия.
Используй ArrayView. И вместо хранения пары float*, size тоже храни ArrayView.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[6]: ссылка на локальный вектор
От: sci_reseacher  
Дата: 16.05.16 17:14
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, sci_reseacher, Вы писали:


_>>const vector<float> & w = d.getX(); // только вот здесь для D d нет ли лишней копии вектора? всегда работает return value optimization?


TB>У тебя везде делается лишняя копия.

TB>Используй ArrayView. И вместо хранения пары float*, size тоже храни ArrayView.

а можно по сути разъяснить, как концепция "ArrayView" позволяет не делать лишней копии в указанной ситуации, когда требуется возвращать
const std::vector<T> &

а доступно: или контейнер
std::vector<T> w;

или указатель по которому можно читать
T *u;

?
Re[7]: ссылка на локальный вектор
От: watchmaker  
Дата: 16.05.16 17:23
Оценка:
Здравствуйте, sci_reseacher, Вы писали:


TB>>Используй ArrayView. И вместо хранения пары float*, size тоже храни ArrayView.


_>а можно по сути разъяснить, как концепция "ArrayView" позволяет не делать лишней копии в указанной ситуации, когда требуется возвращать

_>
_>const std::vector<T> &
_>


Опять же встречный вопрос: «кому требуется»? Концепция view как раз и подразумевает, что больше никому этот вектор не будет нужен, а возвращаться будет сам view. Соответственно, специализированный наследник сможет сам сконструировать view из своих данных (хоть из вектора, хоть из указателя).

То есть использование view позволяет один раз зафиксировать, что невладеющий доступ к массивам или строчкам в программе будет осуществляться через этот тип, а после этого дилеммы об возвращении const vector<int>& уже не возникнет, потому что в нём и не будет надобности.
Re[8]: ссылка на локальный вектор
От: peterbes Россия  
Дата: 16.05.16 17:35
Оценка:
_>в одном классе мне нужен std::vector<T>, в другом T*, т.к. это две разные реализации класса, работающие на разных устройствах --- а пользователь их может выбирать.

В чём разница, в первом вопросе этого не было, но было копирование.

Да и хрен с ним, а причем тут vector, который у вас возвращался дичайшим никогда невозвратным образом? Тогда берите слайсы над байтовым массивом и работайте напрямую, возвращая клиенту косвенные индексы

_>P.S. "академические навороты" нужны чтобы "застолбить" единый интерфейс


Можете пояснить?
Re[7]: ссылка на локальный вектор
От: T4r4sB Россия  
Дата: 16.05.16 19:10
Оценка:
Здравствуйте, sci_reseacher, Вы писали:

_>а можно по сути разъяснить, как концепция "ArrayView" позволяет не делать лишней копии в указанной ситуации, когда требуется возвращать

_>
_>const std::vector<T> &
_>


Потому что тебе не нужно возвращать ссылку на вектор. Тебе надо возвращать ArrayView. Тебе же нужно только что? Количество элементов и доступ к элементам. И всё. И этот ArrayView тебе это предоставил. Но надо, конечно, понимать, что время жизни ArrayView должно быть меньше, чем у вектора. Например, возвращать ArrayView на участок вектора, только что созданного на стеке — это очень плохо.
Смысл в том, что ArrayView можно построить на векторе без переголовы, а наоборот — нельзя.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[8]: ссылка на локальный вектор
От: Ops Россия  
Дата: 16.05.16 20:52
Оценка: +1
Здравствуйте, uzhas, Вы писали:

U>или обратись к Стандарту

Не наш случай. Сей адепт интернет-толкований и научного тыка по компиляторам стандарт не признает.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: ссылка на локальный вектор
От: Erop Россия  
Дата: 17.05.16 04:38
Оценка: +1
Здравствуйте, sci_reseacher, Вы писали:

_>Можно ли передавать ссылку на вектор, созданный локально?

_>
_>struct A
_>{
_>    float* X_;
_>    int size;
_>    const vector<float> & getX(){
_>        vector<float> tmp(X_,X_+size);
_>        return tmp;
_>    }
    
_>};
_>

_>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'ов копировать в вектор? Можно же просто возвращать два указателя, в качестве итераторов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.