В C++/CX, почему неиспользуемые параметры шляпы ^ не генерируют предупреждения?

Я работаю над приложением для Магазина Windows и только что поднял уровень предупреждений Visual Studio до 4, поэтому исправил предупреждения о параметрах без ссылок. В процессе я заметил, что управляемые инфраструктурой параметры без ссылок (^) не генерируют предупреждение C4100, как другие «формальные» параметры без ссылок. Чтобы проиллюстрировать, что я имею в виду:

void Method(CNonFrameworkManaged* pObject)
{
    // Warning C4100: 'pObject' : unreferenced formal parameter
}

void Method(CFrameworkManaged^ spObject)
{
    // No warning
}

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

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


person FrolickingFerret    schedule 15.04.2013    source источник
comment
Я компилирую свой проект без поддержки CLR C++/CX и C++/CLI являются взаимоисключающими: невозможно объединить C++/CX с поддержкой CLR в рамках одного проекта.   -  person James McNellis    schedule 19.04.2013


Ответы (1)


Тип шляпы — это форма интеллектуального указателя, поэтому у каждого типа шляпы есть деструктор, который освобождает право собственности на объект, на который указывает указатель. Хотя spObject не упоминается по имени в исходном коде, объект ссылается сгенерированным компилятором вызовом деструктора в конце функции.

Когда компилятор проверяет локальные переменные, на которые нет ссылок, он находит эту ссылку и не выдает предупреждение. Обычная (непараметрическая) локальная переменная должна иметь имя, и было бы проблематично, если бы компилятор выдавал предупреждения «локальная переменная без ссылки» для таких локальных переменных, которые существуют исключительно для уничтожения (например, типы RAII, такие как lock_guard). Предупреждения C4101 и C4189 выдаются для локальных переменных без параметров, на которые нет ссылок. (Может ли компилятор обрабатывать параметры по-другому? Возможно. Но это не так.)

Обратите внимание, что C4100 не выдается ни для одного параметра типа, имеющего деструктор:

struct A { };
struct B { ~B() { } };

void f(A a) { } // C4100 is issued for 'a'
void f(B b) { } // C4100 is not issued for 'b'
person James McNellis    schedule 19.04.2013
comment
Спасибо, это отличный ответ. Я полагаю, что также возникает вопрос о том, позволит ли компилятору закомментировать имя параметра ^, на который нет ссылки, удалить вызов конструктора/деструктора интеллектуального указателя? - person FrolickingFerret; 02.05.2013
comment
@FrolickingFerret: поведение одинаково независимо от того, имеет ли параметр имя. Тем не менее, компиляция может во многих случаях исключить вызовы AddRef и Release на шляпе, потому что компилятор полностью знает, как работает подсчет ссылок COM (в отличие, скажем, от того, как работает подсчет ссылок shared_ptr — для компилятора shared_ptr похож на любой другой тип). Я могу написать более подробное объяснение, но, вероятно, не раньше пятницы. - person James McNellis; 02.05.2013
comment
Это очень интересно. Имеет смысл, что компилятор сможет применить elision к шляпе. Я действительно не рассматривал это по сравнению с такими вещами, как shared_ptr. т - person FrolickingFerret; 12.07.2013