В основном Вы смотрите на каждую операцию и видите, имеют ли операции "смысл", учитывая Ваше знание того, как это должно быть в состоянии работать.
, Например, при присоединении к двум таблицам, A и B на их соответствующих столбцах C и D (C=B.D), и план показывает сканирование кластерного индекса (термин SQL Server - не уверенный в термине оракула) на таблице A, тогда вложенный цикл соединяет с серией кластерного индекса, ищет на таблице B, Вы могли бы думать, что была проблема. В том сценарии Вы могли бы ожидать, что механизм сделает пару индексных сканирований (по индексам на столбцах, к которым присоединяются) сопровождаемый слиянием. Дальнейшее расследование могло бы показать плохую статистику, заставляющую оптимизатор выбирать тот шаблон соединения или индекс, который на самом деле не существует.
Без сообщения об ошибке я не совсем уверен, на что может жаловаться компилятор, но могу логически объяснить причину:
В строке:
bar(foo());
Возвращаемое значение of foo () - временный A; он создается вызовом foo (), а затем уничтожается, как только возвращается bar (). Выполнение неконстантной операции (т. Е. Операции, изменяющей временное значение A) не имеет смысла, поскольку объект A разрушается сразу после этого.
Если присмотреться немного подробнее, это виртуальный дубликат этого вопроса:
Почему неконстантная ссылка не может быть привязана к временному объекту?
, что дает отличный ответ.
Почему аргумент функциональной панели должна быть константной ссылкой, а не просто ссылка?
Аргумент bar () не обязательно должен быть константной ссылкой. Но при передаче объектов в параметр функции это наиболее эффективный способ, когда объект не будет изменен функцией.
Ссылка должна ссылаться на объект const
, потому что вы все равно не сможете использовать изменения в нем. Сравните следующие фрагменты кода:
void bar(A&);
A x = foo();
bar(x);
if (x.member) {...} else {...}
и
void bar(A const&);
bar(foo());
if (//x? we don't have any x! We can't branch here!
В то время как в первом примере возможность изменения объекта может значительно изменить выполнение последующего кода, во втором у нас просто нет средств (имя переменной мы могли бы обратиться к), чтобы сделать это. Следовательно, мы можем использовать только ссылку на const, которая хочет, чтобы объект не изменялся.
Компилятор ищет bar (const foo &)
, потому что вы передаете const ссылку на foo
в bar
в bar (foo ())
- это потому, что вы передаете ссылку на временную переменную, которая не будет существовать, как только bar
вернет .
Нет варианта использования, в котором имеет смысл изменять foo
внутри bar
через ссылку, потому что она не будет существовать, когда вы вернетесь из bar ().
Таким образом, компилятор применяет это, чтобы предотвратить скрытые ошибки, когда разработчик передает ссылку на временную и обновляет временный объект, который исчезнет после возврата метода.