AUTOSAR C++14 Rule A6-2-2

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

Описание

Управляйте определением

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

Объяснение

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

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

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

  • Преобразование типа

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

Временные объекты уничтожаются однажды выражение, которое требует, чтобы их конструкция была полностью оценена. Например, в выполнении выражения 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 остается незащищенным от проблем параллелизма.

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

Реализация 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 объект называют.

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

Группа: операторы
Категория: необходимый, автоматизированный