Передача массива размером 9 и становится размером 1

0

простой вызов по ссылке

void foo(int* A)
{
    // ...
}

void main()
{
    int A[] = {1,1,1,1,1,1,1,1,1};
    foo(A);
}

не уверен, почему, но это уменьшает размер массива и проигрывает/утечка информации о массиве....

  • 4
    Используйте std::array или std::vector и избавьте себя от боли. PS: sizeof внутри foo даст вам размер указателя, потому что он вычисляется во время компиляции (он не мог знать, на что указывает указатель).
  • 1
    «Простой звонок по ссылке», нет, это не так. это вызов по значению, передающий указатель. void main , нет , это недопустимо с ++ (или с, если на то пошло). «уменьшение размера», нет, только очевидно, но этот так называемый распад - наследие C, довольно проблематичное.
Показать ещё 4 комментария
Теги:
arrays

4 ответа

1
Лучший ответ

Вы должны полностью отказаться от массивов C-стиля и использовать std::array. Просто сравните это (что является решением вашей проблемы):

void foo(int* A, std::size_t size) {
    // ...
}

int main() {
    int A[] = {1,1,1,1,1,1,1,1,1};
    foo(A, (sizeof(A) / sizeof(int)));
}

чтобы:

template<std::size_t Size>
void foo(const std::array<int, Size>& array) {
    // ...
}

int main() {
    std::array<int, 9> A {{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }};
    foo(A);
}

Разве это не красиво? Или просто взгляните на то, как великолепно это с std::vector:

void foo(const std::vector<int>& vector) {
    // vector.size() is the size
}

int main() {
    std::vector<int> A = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    foo(A);
}

И если вы действительно хотите, чтобы foo был универсальным алгоритмом, я просто буду дуть с итераторами:

template<class Iterator>
void foo(Iterator begin, Iterator end) {
    // ...
}

int main() {
    std::array<int, 9> A {{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }};
    std::vector<int> B = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    foo(A.begin(), A.end());    // not a single problem
    foo(B.begin(), B.end());    // was given that day
}

C++ имеет удивительную (возможно) стандартную библиотеку и удивительную систему типов (если вы не упускаете C "унаследованные" функции, такие как void*): используйте их.

  • 0
    +1 Да, это так :)
2

Вы передаете указатель на первый элемент массива. Создайте свою функцию с помощью прототипа

void foo (int * A, int size);

Вы все равно сможете получить доступ к A [0... size-1], как обычно.

1

не уверен, почему, но это уменьшает размер массива и проигрывает/утечка информации о массиве....

В foo() sizeof(A) == 8 не потому, что это "утечка" информации, а потому, что 8 - это размер указателя типа int*. Это верно независимо от того, сколько целых чисел A было инициализировано в main().

Это может пролить свет на то, что происходит:

#include<iostream>
using namespace std;

void foo(int* A)
{
  cout << "foo: " << sizeof(A) << endl; // 8
}

void bar(int A[])
{
  cout << "bar: " << sizeof(A) << endl; // still 8
}

int main()
{
  int A[] = {1,1,1,1,1,1,1,1,1};
  cout << "main: " << sizeof(A) << endl; // 36 (=4*9)
  foo(A);
  bar(A);
  return 0;
}

Вывод:

main: 36
foo: 8
bar: 8

В main sizeof "знает" размер A[] - это sizeof (int) * length = 4 * 9 = 36. Эта информация теряется, когда A[] передается указателю A* в foo.

Что, если мы перейдем в A как bar(int A[]). Будет ли это сохранять длину массива? Нет! В этом случае sizeof(A) по-прежнему равен 8, размер указателя. Только в main компилятор сохраняет информацию о размере массива A

Если вы хотите, чтобы ваши функции знали размер массива, используйте шаблон std::vector<int> или перейдите в размер отдельно.

Вот еще одно обсуждение этого вопроса: когда функция имеет параметр массива определенного размера, почему она заменяется указателем?

0

Правильный способ передачи массива по ссылке

void foo(int (&A) [9])
{
    // sizeof(A) == sizeof(int) * 9
}

общий способ таков:

template <std::size_t N>
void foo(int (&A) [N])
{
    // sizeof(A) == sizeof(int) * N
}

Вы можете использовать std::array (требуется С++ 11), у которого синтаксис более интуитивно понятен

template <std::size_t N>
void foo(std::array<int, N> &A)
{
    // A.size() == N
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню