передача ссылочным C++

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

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

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

10
задан klew 16 February 2010 в 13:50
поделиться

10 ответов

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

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

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

5
ответ дан 3 December 2019 в 18:33
поделиться

Я согласен с большинством других ответов.

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

-121--234765-

Попробуйте:

$url = 'http://blabla/blablabla/dut2a/news.php';
$tokens = explode('/', $url);
echo $tokens[sizeof($tokens)-2];

Предполагается, что $ tokens содержит не менее 2 элементов.

-121--1398501-

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

4
ответ дан 3 December 2019 в 18:33
поделиться

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

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

1
ответ дан 3 December 2019 в 18:33
поделиться

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

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

void some_function(const some_object& o);

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

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

1
ответ дан 3 December 2019 в 18:33
поделиться

Попробуйте:

 $parts = explode('/', 'your_url_here');
 $last = end($parts);
-121--1398504-

Вероятно, вы отправите редактируемое содержимое обратно на сервер. Поэтому вас не должно волновать, есть ли тэгов абзаца или разрыва на месте, когда пользователь редактирует, потому что вы можете разобрать HTML перед отправкой (или на сервере, если хотите) и заменить экземпляры абзацев разрывами. Таким образом, очередь UNDO остается в рабочем состоянии для пользователя, но позволяет иметь такой же чистый HTML, как требуется.

Я также предположу, что вы точно узнаете, какие элементы DIV будут иметь contentEditable. Перед отправкой формы можно запустить каждый contentEditable div с помощью следующей функции:

function cleanContentEditableDiv(div) {
  var htmlString = div.innerHTML;
  htmlString     = htmlString.replace(/<\/p>/gim,"<br/>");
  htmlString     = htmlString.replace(/<p>/gim,"");
  return htmlString;
}

И вы вызываете это в цикле (который итерирует через все contentEditable DIV, используя массив я вызову ceDivs), как это:

ceDivs[i].contentEditable = false; // to make sure IE doesn't try to coerce the contents again

и затем:

ceDivs[i].innerHTML = cleanContentEditableDiv(ceDivs[i]);

Улучшением этого (особенно если вы не хотите делать это во время подачи) может быть очистка содержимого каждого такого div в любое другое время (onblur, что угодно) и присвоение содержимого каждого ceDiv своему собственному невидимому элементу формы для последующей подачи. Используется в сочетании с вашим собственным предложением CSS выше, это может работать для вас. Это не сохраняет ваши буквенные требования к букве (то есть это не дает Javascript заставить IE вести себя иначе, чем он был закодирован под обложками, чтобы вести себя), но для всех практических целей эффект тот же. Пользователи получают то, что хотят, а вы получаете то, что хотите.

Пока вы находитесь в нем, вы также можете очистить строки пространства в IE. Если пользователь вводит несколько мест (как некоторые все еще делают после периодов), то IE вставляет не [космос] [космос], а [космос] & nbsp;, начальный символ пробела (String.fromCharCode (32)) плюс столько же & nbsp; объекты остаются в космос прогоне.

-121--1363018-

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

  1. вы не хотите изменять переданный объект
  2. вы хотите изменить объект и не хотите сохранять старый объект нетронутым

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

1
ответ дан 3 December 2019 в 18:33
поделиться

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

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

void foo( type array[100] );

Компилятор на самом деле обрабатывает:

void foo( type *array );

Независимо от размера массива (здесь есть две распространенные ловушки: полагаясь на то, что массив является массивом внутри foo , и полагая, что он будет гарантированно содержать 100 элементов.

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

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

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

// 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 элементов, и в некоторых случаях вы можете захотеть выполнить ту же операцию в разные размеры массивов. Вот два решения: шаблон функции в размере массива, который обеспечит безопасную по размеру реализацию для каждого используемого размера - большее время компиляции и двоичный размер, шаблон компилируется для каждого разного размера - или с использованием пароля синтаксис по значению, который приведет к распаду массива - небезопасный по размеру, который должен быть передан как дополнительный аргумент, меньшее время компиляции и двоичный размер. Третий вариант объединяет оба:

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

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

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

8
ответ дан 3 December 2019 в 18:33
поделиться

Как создать один метод EnityButtons , который включает/отключает кнопки в соответствии с заданным критерием, таким как "enable cmdRight2, только если.... это правда ".

Затем вызовите метод всякий раз, когда некоторые критерии могут измениться. Преимущество этого по сравнению с путями, которые вы делаете сейчас, заключается в том, что критерии в методе являются «абсолютными» (в том, что кнопки либо включены, либо отключены в одном переходе), а не «относительными» (включить кнопку, когда пользователь делает то или иное).

Можно также вызвать этот метод из события Application.Idle вместо вызова его в ответ на какое-либо действие пользователя.

EDIT

Объявите следующий метод:

private void EnableButtons()
{
    controlX.Enabled = (<condition...>);
    controlY.Enabled = (<condition...>);
}

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

public Form1()
{
    // Other code...

    Application.Idle += new <The respective event handler>;
}

Затем объявите метод с соответствующей подписью для события и вызовите EnityButtons там. Этот метод вызывается в ситуациях, когда приложение находится в состоянии «простоя» (ожидание действий пользователя).

-121--5044375-

Проблема заключается в том, что элементы удаляются один за другим, поэтому, когда остается только один предмет, по существу, выбирается один предмет, поэтому программа включает cmdRight. Самый простой способ обойти это - иметь

cmdRight2.Enabled = false;
cmdRight.Enabled = false;

в конце метода cmdRight2_Click.

-121--5044376-

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

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';
}

-- изменить

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

-- изменить

О, так что вы говорите о векторах. Итак, тогда правила большого пальца:

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

Пропустил ли я что-то?

- изменить

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

Спасибо, дрибеас.

1
ответ дан 3 December 2019 в 18:33
поделиться

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

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

0
ответ дан 3 December 2019 в 18:33
поделиться

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

0
ответ дан 3 December 2019 в 18:33
поделиться

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

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

0
ответ дан 3 December 2019 в 18:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: