Справочник по параметрам C ++ - PullRequest
1 голос
/ 26 ноября 2008

void (int []) { а [5] = 3; // это не верно? }

Можно ли сделать так, чтобы переданный массив был изменен?

Извините за удаление, немного нового здесь ...

У меня есть еще один вопрос, который может ответить на мой вопрос:

Если у меня есть

void Test(int a) {
}

void Best(int &a) {
}

эквивалентны ли эти два утверждения?

Test(a);
Best(&a);

Ответы [ 6 ]

13 голосов
/ 26 ноября 2008
void Test(int a[]) 
{
    a[5] = 3;
}

просто альтернативный синтаксис для:

void Test(int* a) 
{
    *(a+5) = 3;
}

Массив не передается, только указатель. Исходный массив изменен.

Что касается вашей второй ревизии, учитывая:

void Test(int a) 
{
}

void Best(int &a) 
{
}

тогда

Test(aa);      // Passes aa by value.  Changes to a in Test() do not effect aa
Best(aa);      // Passes aa by reference; Changes to a DO effect aa
Best(&aa);     // Is a syntax error: Passing a pointer instead of an int.
2 голосов
/ 26 ноября 2008

Если вы получаете переменную не по ссылке и не по указателю, это означает, что функция по существу изолирована, получая специальную копию a. Независимо от того, что вы делаете (не пытаясь взломать стек или тому подобное), у вас не будет доступа к этому значению в вызывающем контексте.

Если вы знаете что-то о контексте вызова, вы можете сделать что-то, основываясь на некотором ожидании содержимого стека, но обычно это плохая идея.

Если ваш метод принимает [], который по сути является *, тогда да, вы можете изменить содержимое ячейки, на которую указывает, но вы не сможете изменить сам (указатель), чтобы он указывал на что-то другое.

0 голосов
/ 26 ноября 2008

Ваша оригинальная функция должна работать.
Если вы дадите ему имя:

#include <iostream>

// Arrays always de-generate to pointers.
void plop(int a[])  // Make sure this function has a name.
{
    a[5]    = 3;
}

int main()
{
    int test[]  = { 1,1,1,1,1,1,1,1};

    plop(test);

    std::cout << test[5] << std::endl;
}

Это потому, что массивы всегда распадаются на указатели при передаче в качестве аргумента функции. Так что это всегда должно работать как положено. Предполагая, что вы не индексируете за пределами конца массива. Внутри plop нет способа определить размер передаваемого массива.

0 голосов
/ 26 ноября 2008

Прочитайте приведенный здесь ответ о разнице int[] и int* в списке параметров: Разница между char* и char[]. Я действительно вложил так много любви в этот ответ! :)

Относительно вашего вопроса о функциях Test и Best, Джеймс Керран дал отличный ответ.

0 голосов
/ 26 ноября 2008

Основным мотиватором для передачи массивов по ссылке является предотвращение переполнения стека и ненужного копирования больших объектов. Например, представьте, если бы у меня была такая функция:

void foo(int x[500000000000]);

Стек, вероятно, переполнится при первом вызове функции, если все массивы будут переданы по значению (но, конечно, это явное преувеличение).

Это станет полезным при использовании объектно-ориентированных методов. Предположим, вместо массива у вас было это:

void foo(SomeClass x);

где SomeClass - класс с 500000000000 членами данных. Если бы вы вызвали такой метод, компилятор скопировал бы бит по битам, что, по меньшей мере, было бы очень долгим процессом. По-прежнему применима та же концепция, что и в массивах, но вы должны указать, что она будет использоваться по ссылке вручную:

void foo(SomeClass &x);

(и не пытайтесь сначала создать массив элементов 500000000000, если у вас нет 64-битной машины и много оперативной памяти)

0 голосов
/ 26 ноября 2008

Нет.

Ваши варианты изменения значения вне функции - это вызов по ссылке f (int & a), вызов по указателю f (int * a) и использование глобальной переменной (shudder ...).

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