Russian Qt Forum
Ноябрь 23, 2024, 08:14 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 ... 6   Вниз
  Печать  
Автор Тема: Современные одномерные и двумерные массивы на C++  (Прочитано 50113 раз)
vulko
Гость
« Ответ #15 : Октябрь 29, 2014, 12:41 »

Тем что можно забыть правильно освободить ресурсы, нужно писать лишний код по освобождению ресурсов, а если пользователь вводит и вводит собака, то придётся предусмотреть выделение дополнительных ресурсов

И что, в случае нижеприведенного кода тоже ничего не нужно освобождать?)

Код:
struct DataItem {
   int dataType;
   void *data;
};

typedef vector< vector<DataItem *> > DataItemContainer;

DataItemContainer *allOfMyData;

allOfMyData = new DataItemContainer;

...
Записан
8Observer8
Гость
« Ответ #16 : Октябрь 29, 2014, 13:16 »

Цитировать
Зачем передавать в функции v.data()?
Можно хранить указатель на вектор и не боятся передавать его в функции. Либо передавать вектор по ссылке... чтобы не испортили по константной ссылке.

Хорошо, вот как я делаю:

Код
C++ (Qt)
   std::vector<GLfloat> m_vertices;
   std::vector<GLfloat> m_textures;
   std::vector<GLuint> m_indices;
 
   // ...
 
   m_vertices.push_back( -50.0f );    //X
   m_vertices.push_back( -50.0f );    //Y
   m_vertices.push_back( 0.0f );      //Z
 
   m_vertices.push_back( 50.0f );     //X
   m_vertices.push_back( -50.0f );    //Y
   m_vertices.push_back( 0.0f );      //Z
 
   m_vertices.push_back( 50.0f );     //X
   m_vertices.push_back( 50.0f );     //etc..
   m_vertices.push_back( 0.0f );
 
   // ...
 
   glVertexPointer( 3, GL_FLOAT, 0, m_vertices.data() );
   glTexCoordPointer( 2, GL_FLOAT, 0, m_textures.data() );
   // ...
 

glVertexPointer это функция из OpenGL. Она принимает указатель на GLfloat (GLfloat - это typedef для float). Первый параметр у неё - это по сути количество столбцов. Для glTexCoordPointer - так же

Пойдёт, как ответ на вопрос"Зачем передавать в функции v.data()?"?
« Последнее редактирование: Октябрь 29, 2014, 13:19 от 8Observer8 » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #17 : Октябрь 29, 2014, 13:19 »

Цитировать
Неважно кто собирал, важно не забывать что stl сильно зависит от платформы/компилятора.
И вообще stl штука неоднозначная. Например легко может случиться, что на одной платформе size() будет O(1), а на другой O(N).
Может отличаться внутренняя реализация stl, но стандарту она должна соответствовать.. Я сейчас не говорю о "самом строгом" MSVC.. А приведённый пример с size - касается, например, списка (std::list), но в стандарте C++98 так и говориться: Complexity: Up to linear.
Т.е. никаких непредсказуемых ситуаций) (про MSVC опять молчу)

Цитировать
Все операции вставки/извлечения в/из stl контейнера происходят по значению. Т.е. объект копируется.
 
Нет, в с++11 не всегда..

Цитировать
Гораздо лучше держать контейнер из указателей.
Аха... особенно вектор)

Цитировать
В чем конкретно удобство работы с вектором? Для него даже оператор [] перегрузили чтобы он от обычного массива не отличался.
Да хотя бы из-за того, что он знает свой размер.. Может динамически изменяться, имеет оператор присваивания и конструктор копирования, а в с++11 еще и соответствующие move оператор и конструктор..  У вас какое то поверхностное представление о stl..

Цитировать
Создавать динамически объекты все равно приходится очень часто. И даже не потому что везде вектора не воткнуть, а просто потому что долго живущие объекты должны жить в куче.
Это вообще бред какой то..

 
 

    
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
vulko
Гость
« Ответ #18 : Октябрь 29, 2014, 13:50 »

Может отличаться внутренняя реализация stl, но стандарту она должна соответствовать.. Я сейчас не говорю о "самом строгом" MSVC.. А приведённый пример с size - касается, например, списка (std::list), но в стандарте C++98 так и говориться: Complexity: Up to linear.
Т.е. никаких непредсказуемых ситуаций) (про MSVC опять молчу)
Ну зачем молчать про MSVC. Есть те кто пользуют stl и MSVC.

Цитировать
Цитировать
Все операции вставки/извлечения в/из stl контейнера происходят по значению. Т.е. объект копируется.
 
Нет, в с++11 не всегда..
 
с++11 кроме gcc (начиная с определенной версии) кто ещё поддерживает?


Цитировать
Цитировать
Гораздо лучше держать контейнер из указателей.
Аха... особенно вектор)
почему нет? чем вектор из указателей плох?

Цитировать
Да хотя бы из-за того, что он знает свой размер.. Может динамически изменяться, имеет оператор присваивания и конструктор копирования, а в с++11 еще и соответствующие move оператор и конструктор..  У вас какое то поверхностное представление о stl..
размер да, неоспоримое преимущество вектора.
при изменении размера вектора он копируется в новое место или фрагментируется?
с++11 как уже говорил кроме gcc никто толком и не старается соответствовать.
move оператор не для вектора придумывали. вектор можно хоть memcpy скопировать. это преимущество скорее для других контейнеров.

Цитировать
Цитировать
Создавать динамически объекты все равно приходится очень часто. И даже не потому что везде вектора не воткнуть, а просто потому что долго живущие объекты должны жить в куче.
Это вообще бред какой то..   
Бред это писать что современный массив это вектор, а классический массив это пережиток прошлого.
Записан
vulko
Гость
« Ответ #19 : Октябрь 29, 2014, 14:00 »

Цитировать
Зачем передавать в функции v.data()?
Можно хранить указатель на вектор и не боятся передавать его в функции. Либо передавать вектор по ссылке... чтобы не испортили по константной ссылке.

Хорошо, вот как я делаю:

Код
C++ (Qt)
   std::vector<GLfloat> m_vertices;
   std::vector<GLfloat> m_textures;
   std::vector<GLuint> m_indices;
 
   // ...
 
   m_vertices.push_back( -50.0f );    //X
   m_vertices.push_back( -50.0f );    //Y
   m_vertices.push_back( 0.0f );      //Z
 
   m_vertices.push_back( 50.0f );     //X
   m_vertices.push_back( -50.0f );    //Y
   m_vertices.push_back( 0.0f );      //Z
 
   m_vertices.push_back( 50.0f );     //X
   m_vertices.push_back( 50.0f );     //etc..
   m_vertices.push_back( 0.0f );
 
   // ...
 
   glVertexPointer( 3, GL_FLOAT, 0, m_vertices.data() );
   glTexCoordPointer( 2, GL_FLOAT, 0, m_textures.data() );
   // ...
 

glVertexPointer это функция из OpenGL. Она принимает указатель на GLfloat (GLfloat - это typedef для float). Первый параметр у неё - это по сути количество столбцов. Для glTexCoordPointer - так же

Пойдёт, как ответ на вопрос"Зачем передавать в функции v.data()?"?

Я не совсем верно сформулировал мысль видимо...

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

Да, где-то он упрощает жизнь. А где-то нет. Но не стоит забывать что это контейнер. И не надо называть его массивом.

П.с. например есть файл на диске, в котором 2 000 000 вертексов. Неужели нужно их каждый добавить в вектор а потом отдать с помощью v.data()? или все же лучше обычный массив GLFloat'ов создать?)
Записан
8Observer8
Гость
« Ответ #20 : Октябрь 29, 2014, 14:10 »

Можно полностью отказаться от классических статических и динамических массивов и заменить их std::vector. Если у вас есть либа написанная не на Qt (а так чаще всего и будет), а на STL, то там функции, скорее всего, будут принимать в качестве параметра указатель. Вот тут можно использовать vec.data() и нет проблем. Ещё раз повторю моё мнение, что про классические статические и динамические массивы можно забыть, они устарели и везде использовать std::vector

Цитировать
П.с. например есть файл на диске, в котором 2 000 000 вертексов. Неужели нужно их каждый добавить в вектор а потом отдать с помощью v.data()? или все же лучше обычный массив GLFloat'ов создать?)
Обычный массив в топку! Можно сделать vec.resize( сколько_нужно );

Используя С++11, можно вообще никогда не писать new и delete. Для создания объектов из кучи есть std::make_shared (в программе может быть несколько ссылок на объект). А в C++14 появился std::make_unique (одна ссылка на объект)
Записан
vulko
Гость
« Ответ #21 : Октябрь 29, 2014, 14:22 »

Обычный массив в топку! Можно сделать vec.resize( сколько_нужно );

Используя С++11, можно вообще никогда не писать new и delete. Для создания объектов из кучи есть std::make_shared (в программе может быть несколько ссылок на объект). А в C++14 появился std::make_unique (одна ссылка на объект)

А ничё что vector.resize() это О(n)?

Никогда не писать new и delete это как? Все само создастся?)))
Классы тоже будешь в вектор добавлять, чтобы ни в коем случае не писать самому new и delete? Улыбающийся)

Короче прекрати нести чушь!

Ну а стандарту с++11 далеко не все следуют.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #22 : Октябрь 29, 2014, 18:05 »

Ещё раз повторю моё мнение, что про классические статические и динамические массивы можно забыть, они устарели и везде использовать std::vector

В рамку и на стенку Улыбающийся. Скотт Мейерс и то скромнее высказывается.

"Классические статические и динамические массивы" и std::vector никак друг другу не мешают. Просто надо знать и понимать, что и в каких случаях лучше использовать. И чтобы подобному учить других, самому знать об этом нужно очень хорошо.

Например, даже современному OpenGL все эти std::vector совершенно до лампочки, он спокойно кушает старые дедовские статические и динамические массивы Улыбающийся.
Записан

Пока сам не сделаешь...
8Observer8
Гость
« Ответ #23 : Октябрь 29, 2014, 22:27 »

Скотта Майерса читаю и прислушиваюсь к нему. Но я пытаюсь всегда своими мозгами пользоваться, а в слепую стараюсь никому не доверять

Цитировать
Просто надо знать и понимать, что и в каких случаях лучше использовать.
Хорошо, вы знаете и понимаете, тогда приведите несколько убедительных примеров. Где лучше применять вектор, а где статический и динамический массивы. Я пока своими глазами не увижу, не поверю

Цитировать
Например, даже современному OpenGL все эти std::vector совершенно до лампочки, он спокойно кушает старые дедовские статические и динамические массивы
Ну и что. Мы спокойно можем работать с std::vector, а функциям OpenGL передавать указатель на буфер vec.data()

Цитировать
А ничё что vector.resize() это О(n)?
Я привёл этот пример, как эквивалент статического массива. В том смысле, что всё равно вы не сможете создать большой статический массив в стеке, и здесь в vector.resize( n ) подразумевается небольшое число n. Тем более что если мы взяли память из кучи и нам её не хватило, то придётся запрашивать бОльшей буфер с помощью new, а потом копировать данные из старого массива в новый. И врядли мы напишем более эффективную версию, чем vec.push_back()

Статический массив
Код
C++ (Qt)
int arr[10]
 

Заменяем на:
Код
C++ (Qt)
std::vector<int> arr(10);
 

Или на это:
Заменяем на:
Код
C++ (Qt)
std::vector<int> arr;
arr.resize( 10 );
 

Цитировать
Никогда не писать new и delete это как? Все само создастся?)))
Классы тоже будешь в вектор добавлять, чтобы ни в коем случае не писать самому new и delete?

А вот так:
Код
C++ (Qt)
#include <iostream>
#include <memory>
 
struct Person
{
   std::string firstName;
   std::string lastName;
};
 
int main()
{
   // Create object
   auto p = std::make_shared<Person>();
 
   // Use object
   p->firstName = "Ivan";
   std::cout << p->firstName << std::endl;
 
   return 0;
}
 

Вместо этого:
Код
C++ (Qt)
#include <iostream>
 
struct Person
{
   std::string firstName;
   std::string lastName;
};
 
int main()
{
   // Create object
   Person *p = new Person;
 
   // Use object
   p->firstName = "Ivan";
   std::cout << p->firstName << std::endl;
 
   // Delete object
   delete p;
 
   return 0;
}
 
« Последнее редактирование: Октябрь 29, 2014, 22:31 от 8Observer8 » Записан
vulko
Гость
« Ответ #24 : Октябрь 30, 2014, 09:55 »

Я привёл этот пример, как эквивалент статического массива. В том смысле, что всё равно вы не сможете создать большой статический массив в стеке, и здесь в vector.resize( n ) подразумевается небольшое число n. Тем более что если мы взяли память из кучи и нам её не хватило, то придётся запрашивать бОльшей буфер с помощью new, а потом копировать данные из старого массива в новый. И врядли мы напишем более эффективную версию, чем vec.push_back()

То что вектор умеет увеличиваться в размерах автоматом, это может и плюс, когда нужно 100 элементов добавить. А если вертексов пару миллионов? Ты попробуй сперва код такой напиши, и посмотрим сколько времени уйдет тупо на ресайз вектора.
Вектор не фрагментриуется, как лист например, поэтому при ресайзе будет происходить копирование.


Цитировать
Тем более что если мы взяли память из кучи и нам её не хватило, то придётся запрашивать бОльшей буфер с помощью new, а потом копировать данные из старого массива в новый.
А вектор наверное работает магическим образом!
Не вызывает new и уж тем более не копирует память при ресайзе...))))
Вектор работает точно также.
А если вектор из указателей, то и за памятью придется следить.


Цитировать
В том смысле, что всё равно вы не сможете создать большой статический массив в стеке
При чем тут я? Никто не может. Так мир устроен.
Вектор свои данные хранит в куче, а на стэке живет лишь сам объект.
Так что ресайз вектора ничуть не быстрее new[] + copy!


Цитировать
И врядли мы напишем более эффективную версию, чем vec.push_back()

Пожалуйста, нижеприведенный аналог работает быстрее!
Код:
data[pos] = dt;


Цитировать
А вот так:
***
Вместо этого:

Всегда нравились дурацкие примеры...

Никто никогда так не делает в жизни!
А если кто-то так делает, то его нужно бить по голове.

Потому что вызов Person *p = new Person, подразумевает что этот объект не будет в конце этой функции удален.
Если же объект используется в рамках одной функции, то писать нужно Person p;

Цитировать
Код:
    // Create object
    Person *p = new Person;
 
    // Use object
    p->firstName = "Ivan";
    std::cout << p->firstName << std::endl;
 
    // Delete object
    delete p;


С++11 стандарты, как я уже не раз отмечал, имеет смысл использовать только если все это будет компилироваться в gcc начиная с некоей версии.
А что делать если нужно пользовать msvsc?
Если не хочется париться по поводу управления памятью, лучше простой перейти на жабу. Да и с кроссплатформенностью там куда лучше.


Цитировать
Скотта Майерса читаю и прислушиваюсь к нему. Но я пытаюсь всегда своими мозгами пользоваться, а в слепую стараюсь никому не доверять
Ну так и не надо слепо верить в с++11 стандарты.
И думать нужно головой, а не тупо советовать всем использовать всегда и везде вектор, потому что это стильно, модно, молодежно.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Октябрь 30, 2014, 10:35 »

Попробуем сделать это интересным

!)
Они пишут эту дурацкую конструкцию, которой место на свалке:  float *ptrarray = new float [10];
Эта "дурацкая" конструкция легко может оказаться выгоднее чем вот эта
Код
C++ (Qt)
   std::vector< std::vector<int> > arr( 5 );
 
В последней есть весьма существенный недостаток. Какой?

2) Удалить массив из кучи - просто delete, а вот как освободить память занимаемую вектором (не создавая новой переменной) ?

3) Какие действия (примерно) производятся при обращении к вектору, и насколько они могут снизить производительность в Debug? Да, и не надо делать вид что MSVC якобы "не существует".

4) Корректно ли это?
Код
C++ (Qt)
int * a = &vec[0];
 

5) Какая основная причина вынуждающая использовать вместо вектора др контейнеры? Также почему часто либы используют свой класс вместо std::vector?

---
Для меня нормально что если человек написал статью, то такие квешнзы для него - семечки, да еще он расскажет кучу интересного, о чем я и не подозревал !  Улыбающийся
Записан
vulko
Гость
« Ответ #26 : Октябрь 30, 2014, 10:49 »

Удалить массив из кучи - просто delete, а вот как освободить память занимаемую вектором (не создавая новой переменной)

Просто delete vectorPointer; как раз таки удалит вектор, а для удаления элементов вектора есть vector->clear();
Ну а если вектор создавался на стэке, то и удалять его не нужно, сам удалится.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #27 : Октябрь 30, 2014, 10:51 »

а для удаления элементов вектора есть vector->clear();
Это удалит элементы, но не освободит память. Подмигивающий
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #28 : Октябрь 30, 2014, 11:04 »

а для удаления элементов вектора есть vector->clear();
Это удалит элементы, но не освободит память. Подмигивающий
Тогда позвать еще shrink_to_fit.
Записан
vulko
Гость
« Ответ #29 : Октябрь 30, 2014, 11:08 »

а для удаления элементов вектора есть vector->clear();
Это удалит элементы, но не освободит память. Подмигивающий

vector->clear();
vector->resize(0); // или resize(1)

например... да и не проблема это, ведь автор всегда создает вектор на стэке... по крайней мере с его слов. ну и вектор на стеке всегда круче всего на свете.
Записан
Страниц: 1 [2] 3 4 ... 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.577 секунд. Запросов: 23.