exponenta event banner

Правило AUTOSAR C++ 14 A6-2-2

Операторы expression не должны быть явными вызовами только конструкторов временных объектов

Описание

Определение правила

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

Объяснение

Объекты, которые компилятор создает на короткое время, а затем удаляет, являются временными объектами. Компилятор может создавать временные объекты для определенных целей, таких как:

  • Инициализация ссылок

  • Сохранение значений, возвращаемых функциями

  • Типовое литье

  • Обработка исключений

Временные объекты уничтожаются после полной оценки выражения, требующего их построения. Например, при оценке выражения sum = a*b+cкомпилятор создает два временных объекта для хранения результатов операций умножения и сложения. После вычисления выражения оба временных объекта уничтожаются. Их область действия ограничена оператором выражения.

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

  • Непреднамеренно пропущено имя объекта.

  • Вы ожидали, что неназванная переменная останется в области действия до конца блока объявления.

Рассмотрим этот фрагмент кода, где lock_guard создается объект.

void foo(){
std::mutex mymutex;
std::mutex mymutex2;
std::lock_guard<std::mutex> lock{mymutex};
std::lock_guard<std::mutex> {mymutex2};
//...
}
Первое объявление создает lock_guard объект с именем lock. Объект lock защищает mymutex от параллельного доступа несколькими потоками до конца текущего блока. Во второй декларации предпринята попытка аналогичной защиты для mymutex2. Потому что lock_guard объект в этом случае не называется, он уничтожается сразу после объявления. Возможно, непреднамеренно, mymutex2 остается незащищенным от проблем параллелизма.

Избегайте операторов выражений, которые являются только явным вызовом конструктора. Для реализации шаблона инициализации получения ресурсов (RAI) используйте именованные объекты.

Внедрение Polyspace

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

Поиск неисправностей

Если вы ожидаете нарушения правила, но не видите его, обратитесь к разделу Нарушения стандартов кодирования не отображаются.

Примеры

развернуть все

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

#include <cstdint>
#include <fstream>
#include <string>
class MyException {
	MyException(const std::string &);
};
void with_exception() {
	MyException("Exception");              //Noncompliant
	throw MyException("Exception");        //Compliant 
	
};  

Polyspace помечает оператор выражения, который создает неименованный временный объект и не использует его. Если в инструкции используется временный объект, то инструкция соответствует правилу. Например, оператор MyException("Exception"); помечен, так как неназванный объект, созданный явным вызовом конструктора MyException() не используется в инструкции. Заявление throw MyException("Exception"); не помечен, так как неназванный объект используется в качестве аргумента для throw.

Компиляторы уничтожают неназванный lock_guard объект сразу после оператора объявления. Неназванный lock_guard объекты не могут защитить mutex объекты из проблем параллелизма. Polyspace помечает оператор при объявлении неназванного lock_guard объект. Рассмотрим этот код:

#include <cstdint>
#include <mutex>
class A {
public:
	void SetValue1(std::int32_t value) {
		std::lock_guard<std::mutex> {mutex1}; //Noncompliant
		private_value = value;
	}

	void SetValue2(std::int32_t value) {
		std::lock_guard<std::mutex> lock{mutex2}; //Compliant
		private_value = value;
	}
private:
	mutable std::mutex mutex1;
	mutable std::mutex mutex2;
	std::int32_t private_value;
};

  • Заявление std::lock_guard<std::mutex> {mutex1}; объявляет неназванный lock_guard объект. Polyspace помечает заявление.

  • Заявление std::lock_guard<std::mutex> lock{mutex2}; не помечен, так как lock_guard объект имеет имя.

Проверить информацию

Группа: выписки
Категория: Обязательно, Автоматизировано