простой вызов по ссылке
void foo(int* A)
{
// ...
}
void main()
{
int A[] = {1,1,1,1,1,1,1,1,1};
foo(A);
}
не уверен, почему, но это уменьшает размер массива и проигрывает/утечка информации о массиве....
Вы должны полностью отказаться от массивов 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*
): используйте их.
Вы передаете указатель на первый элемент массива. Создайте свою функцию с помощью прототипа
void foo (int * A, int size);
Вы все равно сможете получить доступ к A [0... size-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>
или перейдите в размер отдельно.
Вот еще одно обсуждение этого вопроса: когда функция имеет параметр массива определенного размера, почему она заменяется указателем?
Правильный способ передачи массива по ссылке
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
}
std::array
илиstd::vector
и избавьте себя от боли. PS: sizeof внутри foo даст вам размер указателя, потому что он вычисляется во время компиляции (он не мог знать, на что указывает указатель).void main
, нет , это недопустимо с ++ (или с, если на то пошло). «уменьшение размера», нет, только очевидно, но этот так называемый распад - наследие C, довольно проблематичное.