В C ++ я хочу вернуть массив объектов из функции и использовать его в другом - PullRequest
4 голосов
/ 13 октября 2011

В рамках небольшого проекта, который я делаю для изучения Qt, я пытаюсь вернуть массив объектов через функцию. Затем я хочу получить этот массив правильно и использовать его содержимое. Сейчас я печатаю только пару значений одного атрибута, чтобы попытаться заставить его работать.

Проблема, с которой я столкнулся, заключается в том, что когда я пытаюсь напечатать его содержимое, только первый элемент в массиве содержит правильное значение (остальные кажутся случайными битовыми комбинациями).

Вот функция возврата:

QLine* LinesData::getList(){

  QLine *lineList2[50];
  for(int i = 0; i < 50; i++){
      lineList2[i] = new QLine(10, 10 * i, 100, 100);
  }

return *lineList2;}

А вот функция, которая пытается его использовать:

void runtimeWindow::drawAllLines(){
  QLine* lines = linesData.getList();
  for(int i = 0; i < 5; i++){
      qDebug() << lines[i].x1();
  }
}

Ответы [ 5 ]

2 голосов
/ 13 октября 2011

Используйте std::vector и std:shared_ptr как в:

  std::vector<std::shared_ptr<QLine> >  LinesData::getList(){

  std::vector<std::shared_ptr<QLine> > lineList2;
  for(int i = 0; i < 50; ++i){
      lineList2.push_back(new QLine(10, 10*i, 100, 100));
  }

  return lineList2;}

и

void runtimeWindow::drawAllLines(){
  std::vector<std::shared_ptr<QLine> > lines = linesData.getList();
  for(auto i = lines.begin(); i != lines.end(); ++i){
      qDebug() << (*i)->x1();
  }
}

Если у вас нет std::shared_ptr в компиляторе, используйте версию Boost.

Использование контейнера std::vector позволяет избежать проблем, связанных со стилем C (например, переполнение буфера), а std::shared_ptr выполняет своего рода сборку мусора, когда вы закончите с содержимым вектора, чтобы помочь предотвратить утечки памяти.

Вы также можете сделать это без указателей, выполнив следующие действия:

  std::vector<QLine> LinesData::getList(){

  std::vector<QLine> lineList2(50);
  for(int i = 0; i < 50; ++i){
      lineList2[i].setLine(10, 10*i, 100, 100);
  }

  return lineList2;}

и затем нарисуйте их, используя

void runtimeWindow::drawAllLines(){
  std::vector<QLine> lines = linesData.getList();
  for(auto i = lines.begin(); i != lines.end(); ++i){
      qDebug() << i->x1();
  }
}
1 голос
/ 13 октября 2011

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

Вы также забыли освободитьданные.Это не Java, память не освобождает себя.

Для этого лучше всего использовать std::vector<QLine>.Qt также предоставляет несколько контейнеров, которые могут работать.

0 голосов
/ 13 октября 2011

Вы возвращаете разыменованный lineList2, который является первым указателем QLine *, к которому вы можете получить доступ с помощью строк [0]. Но затем строки [1] и т. Д. Работают не с массивом, а с первым указателем QLine *.

1-й: Используйте контейнеры, такие как std :: vector

2-й: возврат объекта кучи и одновременной передачи владения подвержен утечкам памяти, когда вызывающая функция не уничтожает объект после использования. Вы можете изменить getlist () так, чтобы он ожидал и заполнил контейнер, а не создавал его:

void LinesData::getQlines(std::vector<QLine>& lineList2)
{
  for(int i = 0; i < 50; i++)
      lineList2.push_back(QLine(10, 10*i, 100, 100));
}

3-й: при передаче права собственности на объекты кучи используйте умные указатели, такие как shared_ptr

0 голосов
/ 13 октября 2011
QLine *lineList2[50];

lineList2 - это массив указателей. Они являются смежными, но области памяти, на которые они указывают, могут отсутствовать. Таким образом,

return *lineList2;

Вы возвращаете ссылку на первый объект в последовательности. Но по его адресу вы не можете получить доступ к другим объектам, используя оператор []. Что на самом деле вам нужно сделать, это -

QLine** LinesData::getList(){
    // .....

    return lineList2;
}

void runtimeWindow::drawAllLines(){
  QLine** lines = linesData.getList();
  for(int i = 0; i < 5; i++){
      qDebug() << *(lines[i]).x1(); // or lines[i]->x1();
  }
}

Или просто используйте std::vector, чтобы избежать всей этой боли, как предложил @Ben.

0 голосов
/ 13 октября 2011

Используйте

std::vector<QLine>

или

new QLine[50]

затем верните этот указатель. Вызывающий отвечает за освобождение этого указателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...