Недавно я работал над проектом и решил установить ReSharper C ++ в Visual Studio. Когда он проанализировал мой код, он выдал кучу новых предупреждений (очевидно, у меня плохие привычки кодирования ..). Один из них, который потребовал у меня некоторое время, чтобы выяснить, был Binding r-value to l-value reference is non-standard Microsoft C++ extension
, Я воссоздал предупреждение со следующим кодом:
Type foo(Type t1, Type t2) {
return Type(t1.value & t2.value);
}
Выражение t1.value & t2.value
вызывает предупреждение. Я понимаю вторую часть предупреждения, что означает, что мой код компилируется только из-за расширения Microsoft, и другие компиляторы отказываются компилировать его. Я использую перегруженный оператор, который возвращает объект (называется Datum
) который Type
принимает в качестве параметра конструктора, в качестве ссылки (Type::Type(Datum& dat)
).
Немного поиграв, мне удалось убрать предупреждение с помощью рефакторинга кода:
Type bar(Type t1, Type t2) {
Datum datum = t1.value & t2.value;
return Type(datum);
}
Насколько я понимаю, это функционально эквивалентно коду, который сгенерировал предупреждение. То, что я действительно хотел бы знать, есть ли здесь что-то, о чем я должен знать, потому что я довольно озадачен тем, почему одна функция жалуется, а другая нет.
Я думаю, я понял это. У меня уже был напечатан вопрос, поэтому я собираюсь опубликовать его с тем, что нашел, для справки других. У меня нет достаточных знаний, чтобы вдаваться в подробности, поэтому, пожалуйста, не стесняйтесь расширять или исправлять мой ответ, если он не удовлетворителен 🙂
Это один из способов снять предупреждение: переменная именующий, поэтому можно связать напрямую с опорным параметром хитрого конструктора, в то время как результат выражения Rvalue который не может
Лучшее решение состоит в том, чтобы исправить конструктор, чтобы получить его аргумент по значению или константной ссылке:
Type(Datum dat) // value
Type(Datum const & dat) // constant reference
Теперь вы можете дать аргумент как именующий или Rvalue.
Из того, что я вижу, причина такого поведения в том, что Type
конструктор принимает ссылка к Datum
объект, а не передавать его по значению. Это вызывает предупреждение в Type foo(Type, Type)
потому что компилятор не любит брать ссылку на выражения, что было бы связано с семантикой вычисления выражения.
Опять же, пожалуйста, не стесняйтесь уточнять или исправлять мои выводы, так как это просто результат моих экспериментов и умозаключений.