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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: std::begin std::end принцип работы  (Прочитано 11275 раз)
folax
Гость
« : Март 28, 2018, 14:32 »

Добрый день, нашёл удобный способ находить начало и конец статических массивов. Вопрос почему через функцию не работают данные итераторы begin и end.

Код:
#include <iostream>

using namespace std;

void printArr(int* arr)
{
    int* pBegin = begin(arr);
    int* pEnd   = end(arr);

    while(pBegin != pEnd)
    {
        cout << *pBegin << endl;
        ++pBegin;
    }
}

int main()
{
    int arr[] = { 1, 5, 7, 3, 9, 2 };

    // Почему так можно, каким образом begin и end знают где конце а где начало ?;
    int* pBegin = begin(arr);
    int* pEnd   = end(arr);

    while(pBegin != pEnd)
    {
        cout << *pBegin << endl;
        ++pBegin;
    }

    // А так нельзя!
    printArr(arr);
}
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #1 : Март 28, 2018, 14:49 »

Потому что int [] и int * - это совершенно разные типы. В первом случае тип массива и для него есть возможность узнать начало и конец, во втором - простой указатель, который совсем не обязательно на массив указывает. Посмотрите, как в функцию нужно правильно массив передавать. Но со статическими массивами и голыми указателями лучше не работать. То же самое можно получить с помощью std::array.
Записан

Пока сам не сделаешь...
folax
Гость
« Ответ #2 : Март 28, 2018, 15:41 »

Я думаю понял по какому принципу работают данные функции. Они берут sizeof(массива) / тип массива, получают размер. Начало это std::begin, конец + 1 это std::end. Только вот немного не могу понять это наверно больше вопрос на тему область видимости. В main мы видим весь массив, а в функции только указатель на его начало, так в функцию массив не передаётся по значению.

Код:
#include <iostream>

using namespace std;

void printArrSize(int arr[])
{
    cout << "Function array size: " << sizeof(arr) << endl;
}

int main()
{
    int arr[] = { 1, 5, 7, 3, 9, 2 };
    cout << "Size: " << sizeof(arr) << endl;
    printArrSize(arr);
}

Ответ: 24
Ответ: 4
« Последнее редактирование: Март 28, 2018, 15:43 от folax » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #3 : Март 28, 2018, 15:58 »

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

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Март 28, 2018, 16:19 »

Потому что int [] и int * - это совершенно разные типы.
Код
C++ (Qt)
void Foo1( int arr[3] );
void Foo2( int * arr );
 
По-моему эти ф-ции идентичны и код их одинаков. Разница не в типе как таковом, а в rvalue / lvalue. Тут есть академик, он лучше расскажет

Но со статическими массивами и голыми указателями лучше не работать. То же самое можно получить с помощью std::array.
С чем лучше или хуже - зависит от опыта. Если с адресной арифметикой еще не все гладко, то в итераторную срань лучше не лезть.
Записан
folax
Гость
« Ответ #5 : Март 28, 2018, 17:19 »

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

В начале я хотел функцию чтобы она использовала функции std::begin и std::end для вычисления размера статического массива в экспериментальных целях. Но уже разобрался, выше написал как она работает, как мне кажется. Она не будет работать  через передачу указателя на массив в функцию.
Вся тема вытекла в вопрос на который ответ = Нет нельзя. Вопрос = Можно ли узнать размер статического массива при передачи его в функцию, без указания его размера.

Спасибо большое за ваши ответы и мысли.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #6 : Март 28, 2018, 18:56 »

Если поизвращаться, то можно сделать так:
Код
C++ (Qt)
#include <iostream>
 
using namespace std;
 
template <class Array>
void printArr(Array arr_pointer)
{
   Array& arr    = *reinterpret_cast<Array*>(arr_pointer);
   auto   pBegin = begin(arr);
   auto   pEnd   = end(arr);
 
   while (pBegin != pEnd)
   {
       cout << *pBegin << endl;
       ++pBegin;
   }
}
 
int main()
{
   int arr[] = {1, 5, 7, 3, 9, 2};
 
   printArr<decltype(arr)>(arr);
}
 

Но так лучше не делать Улыбающийся.
Записан

Пока сам не сделаешь...
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Март 28, 2018, 20:07 »

Вопрос = Можно ли узнать размер статического массива при передачи его в функцию, без указания его размера.
В 17 стандарте позаботились о такой функции.
http://en.cppreference.com/w/cpp/iterator/size
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Март 29, 2018, 13:08 »

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

Вывод: от "просто массивов" надо потихоньку уходить (напр с помощью std::array)
Записан
alex312
Хакер
*****
Offline Offline

Сообщений: 606



Просмотр профиля
« Ответ #9 : Март 29, 2018, 14:19 »

По-моему эти ф-ции идентичны и код их одинаков. Разница не в типе как таковом, а в rvalue / lvalue. Тут есть академик, он лучше расскажет
Ха, идентичны ?
а чему будет равет sizeof(arr) внутри функции ?
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #10 : Март 29, 2018, 14:49 »

Если писать без указателей и извращений, то можно так:
Код
C++ (Qt)
#include <iostream>
 
using namespace std;
 
template <class Array>
void printArr(Array& arr)
{
   auto pBegin = begin(arr);
   auto pEnd   = end(arr);
 
   while (pBegin != pEnd)
   {
       cout << *pBegin << endl;
       ++pBegin;
   }
}
 
int main()
{
   int arr[] = {1, 5, 7, 3, 9, 2};
 
   printArr(arr);
}

Можно такой вариант и дальше улучшать, но всё равно, лучше пользоваться std::array.
Записан

Пока сам не сделаешь...
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #11 : Март 29, 2018, 17:53 »

Предлагаю посмотреть std::initializer_list. Может этого класса будет достаточно.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Март 31, 2018, 06:49 »

Ха, идентичны ?
а чему будет равет sizeof(arr) внутри функции ?
Может лучше самому убедиться (это займет неск минут), а потом уж можно и "Ха"  Улыбающийся
Передать массив по ссылке можно так
Код
C++ (Qt)
void Foo1( int (& arr)[3] );
 
Все равно передается адрес, но sizeof вернет размер массива, и вызывающий может подать только массив с 3 эл-тами (а не абы какой). А вот как передать массив по значению - не знаю, может такого и нет. Ну завернуть в структуру - то ясно
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #13 : Апрель 01, 2018, 11:42 »

Игорь, посыл был в том, что сигнатуры отличаются тем, что в Foo1 известен размер на момент компиляции, в Foo2 не известен.
Код
C++ (Qt)
void Foo1( int arr[3] );
void Foo2( int * arr );
 
По-моему эти ф-ции идентичны и код их одинаков.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Апрель 01, 2018, 11:58 »

Игорь, посыл был в том, что сигнатуры отличаются тем, что в Foo1 известен размер на момент компиляции, в Foo2 не известен.
Код
C++ (Qt)
void Foo1( int arr[3] );
void Foo2( int * arr );
 
По-моему эти ф-ции идентичны и код их одинаков.
Ничего подобного, в обоих случаях неизвестен, оба варианта - передача по указателю. [3] удобно для программиста (мол, планируется 3 эл-та), но компилятору все равно
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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