Передавать по ссылке С++

Мой учитель на С++ сказал мне, что вызов по ссылке должен использоваться только в том случае, если я не собираюсь ничего менять на массивах внутри функции. У меня есть некоторые действительно большие векторы, которые я просматриваю в своей программе. Все векторы будут изменены внутри функций. Мои матрицы имеют размеры около [256*256][256][50]...

Есть ли какая-то конкретная причина не использовать ссылку на вызов здесь?

Вызов AFAIK по ссылке должен быть быстрее и потреблять меньше памяти?

Ответ 1

Мой учитель в С++ сказал мне, что вызов по ссылке должен использоваться только в том случае, если я не собираюсь ничего менять на массивах внутри функции.

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

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

Ответ 2

Помимо всех распространенных дискуссий о том, когда и как проходить, возможно, ссылку на константу для не-примитивных типов, массивы здесь весьма специфичны.

Благодаря обратной совместимости с C и там из-за вашей конкретной проблемы: массивы могут быть огромными, массивы никогда не передаются по значению ни на C, ни на С++. Массив будет распадаться на указатель на первый элемент, поэтому, когда вы пишете:

void foo( type array[100] );

Компилятор фактически обрабатывает:

void foo( type *array );

Независимо от того, какой размер массива (две распространенные ошибки: доверие, что array - это массив внутри foo и полагающий, что на нем будет гарантировано 100 элементов.

Теперь на С++ вы можете передавать массивы по ссылке, но ссылка должна быть конкретного типа массива, который включает в себя размер:

void foo_array( type (&array)[100] );

Забавный синтаксис говорит компилятору, что функция примет массив из 100 элементов типа type. Преимущество заключается в том, что компилятор может выполнить проверку размера для вас:

// assuming 'type' is defined
int main() {
   type array0[99];
   type array1[100];

   foo( array0 );     // compiles, but if size=100 is assumed it will probably break
                      // equivalent to: foo( &array0[0] )
   // foo2( array0 ); // will not compile, size is not 100
   foo2( array1 );    // compiles, size is guaranteed to be 100
}

Теперь проблема заключается в том, что ваша функция будет работать только для массива из примерно 100 элементов, и в некоторых случаях вам может понадобиться выполнить одну и ту же операцию в разных размерах массива. Эти два решения: шаблон функции в размере массива, который обеспечит безопасную по размеру реализацию для каждого используемого размера - больше времени компиляции и двоичного размера, шаблон скомпилирован для каждого другого размера - или с помощью метода pass- синтаксис синтаксиса, который приведет к распаду массива - небезопасно по размеру, которое должно быть передано как дополнительный аргумент, меньшее время компиляции и двоичный размер. Третий вариант объединяет оба:

void foo( type *array, int size );
template <size_t N>
void foo( type (&array)[N] ) {
   foo( array, N );
}

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

Теперь перекрестная ссылка очень редко используется с массивами.

Ответ 3

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

Ответ 4

Вы можете передать по ссылке, если:

  • вы не будете изменять переданный объект
  • вы хотите изменить объект и не хотите, чтобы старый объект был не тронут

Когда вы передаете что-то по ссылке, то в функцию передается только указатель. Если вы передаете весь объект, вам нужно его скопировать, поэтому он будет потреблять больше процессора и памяти.

Ответ 5

Обычно, во вводных курсах, они говорят вам, что вы не случайно меняете то, чего не хотели.

Как если бы вы передали в userName по ссылке и случайно изменили его на mrsbuxley, что, вероятно, вызовет ошибки или, по крайней мере, будет запутываться позже.

Ответ 6

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

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

Ответ 7

Чтобы предотвратить случайные изменения, используйте pass-by-const-reference; Таким образом, по умолчанию *, переданный массив не может быть изменен вызываемой функцией.

* Может быть переопределено с помощью const_cast.

Ответ 8

Держись на секунду.. Я боюсь, как люди отвечают на этот вопрос. Массивы, насколько я помню, всегда передаются по ссылке.

void function(int array[])
{
    std::cout << array[0] << '\n';
}

// somewhere else..
int array[2] = { 1, 2 };
function(array); // No copy happens here; it is passed by reference

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

void function(int &array[]) // error here
{ /* ... */ }

Итак, что вы имеете в виду?

Кроме того, многие говорят, что вы должны делать это только в том случае, если вы изменяете содержимое массива внутри функции. Затем, что относительно ссылки на const?

void function(const int arr[])
{
    std::cout << arr[0] << '\n';
}

- отредактировать

Будет ли кто-нибудь, пожалуйста, указать, как не передавать массив по ссылке в С++?

- отредактировать

О, так вы говорите о векторах. Итак, эмпирические правила:

  • Передать ссылку только тогда, когда вы хотите изменить содержимое вектора.
  • Передавайте по ссылке-на-const всякий раз, когда можете.
  • Передайте значение только тогда, когда объект, о котором идет речь, действительно, очень маленький (например, структура, содержащая целое число), или когда это имеет смысл (не могу думать о случае из головы).

Я что-то пропустил?

- отредактировать

  • В случае простых C-массивов рекомендуется передать их по ссылке (например, в void function(int (&array)[100])), если вы хотите убедиться, что массив имеет определенный размер.

Спасибо, dribeas.

Ответ 9

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

Теперь, если метод или функция, которые вы вызываете, не изменяет объект, рекомендуется объявить функцию следующим образом:

void some_function(const some_object& o);

Это приведет к сбою компиляции, если вы попытаетесь изменить состояние объекта внутри тела функции.

Также следует отметить, что массивы всегда передаются по ссылке.

Ответ 10

Наш стиль дома должен НИКОГДА не передавать объект по значению, а всегда передавать ссылку или константу. Мало того, что мы имеем структуры данных, которые могут содержать 100 МБ данных и передавать по значению, будет убийцей приложения, но также, если бы мы проходили трехмерные точки и векторы по стоимости, наши приложения перестали бы останавливаться.

Ответ 11

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

Вы должны сделать выбор здесь, будем ли мы читать данные только объекта или изменять его.

Предположим, у вас есть интерфейс, например

void increament_value(int& a);

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

поэтому С++ предоставляет вам возможность не изменять значение объекта, ссылка на который вы передаете функции, и всегда является хорошим выбором для передачи ссылки const объекта, например,

double get_discounted_amount(const double &amount,double discount){
    return (amount*discount/100);
}

Это гарантирует, что ваше фактическое значение объекта не изменится, но опять же это зависит от цели вашего интерфейса, хотите ли вы его изменить или использовать (читать)