AUTOSAR C++14 Rule A8-4-3

Распространенные способы передать параметры должны использоваться.

Описание

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

Распространенные способы передать параметры должны использоваться.

Объяснение

Если вы следуете известным соглашениям для передающих параметров, разработчик или рецензент могут определить из вашей функциональной подписи, является ли параметр входным параметром, выходным параметром или другим типом параметра.

Эти соглашения обычно используются, чтобы передать параметры функциональному f(X):

  • \in: Если входной тип данных параметров X является дешевым, чтобы скопировать или не может быть скопирован (например, std::unique_ptr введите), передайте параметр значением как f(X). В противном случае передайте параметр const ссылка как f(const X &).

  • : Если тип данных выходного параметра X является дорогим, чтобы переместить, передать параметр ссылкой как f(X &). В противном случае не передавайте параметр, но вместо этого возвращайте значение как X f().

  • В/: Передайте параметр lvalue ссылкой как f(X &).

  • Используйте: Передайте параметр rvalue ссылкой как f(X &&).

  • Вперед: Передайте параметр шаблоном rvalue ссылка как template<typename T> f(T &&).

Реализация Polyspace

Средство проверки отмечает эти неправильные способы передать параметры:

  • В параметрах:

    • Вы передаете значением входной параметр, который является дорогим, чтобы скопировать:

      f(X); //X is expensive to copy

    • Вы передаете ссылкой входной параметр, который является дешевым, чтобы скопировать:

      f(X &); //X is cheap to copy
      f(const X &); //X is cheap to copy

    Средство проверки рассматривает тип данных, который имеет размер меньше, чем дважды sizeof(void *) как дешевый, чтобы скопировать.

  • Параметры:

    • Вы возвращаете значением выходной параметр, который является дорогим, чтобы переместиться:

      X f(); //X is expensive to move

    • Вы передаете ссылкой выходной параметр, который является дешевым, чтобы переместиться:

      f (X &); //X is cheap to move

    Средство проверки рассматривает основополагающий тип данных, который имеет размер меньше чем восемь раз sizeof(void *) как дешевый, чтобы переместиться.

Средство проверки не включает передачу указателями под защитой передачи ссылкой.

Решение нарушения этого правила может иногда включать агрессивные изменения. Например, если средство проверки предполагает, что выходной параметр может быть возвращен значением, но функция уже возвращает значение, необходимо значительно переписать код. Необходимо объединить выходной параметр и уже возвращенное значение в структуру или n-кортеж и затем возвратить эту структуру или n-кортеж. Если выходной параметр и уже возвращенное значение семантически не связано, комбинирование их в структуру не может быть соответствующим. В этом случае добавьте комментарий в результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, относитесь, чтобы Диагностировать, Почему Кодирующие Стандартные Нарушения Не Появляются как ожидалось.

Примеры

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

#include <iostream>
#include <array>
#include <numeric>

typedef struct smallStruct {
    char x;
    char y;
}smallStruct;

void sum(smallStruct& aStruct) { //Noncompliant
    std::cout<<aStruct.x+aStruct.y;
}



typedef struct largeStruct {
    std::array<int,20> arrayOfIntegers;
    int init;
}largeStruct;

void add(largeStruct aStruct) { //Noncompliant
    std::cout<<std::accumulate(aStruct.arrayOfIntegers.begin(),
                     aStruct.arrayOfIntegers.end(), aStruct.init);
}

В этом примере, sum функций и add только считайте содержимое их параметров. Поэтому эти параметры являются входными параметрами.

  • Функциональный sum() с подписью:

    void sum(smallStruct& aStruct);
    берет в качестве аргумента объект типа smallStruct это дешево, чтобы скопировать. Аргумент может быть передан значением вместо ссылки.

  • Функциональный add() с подписью:

    void add(largeStruct aStruct);
    берет в качестве аргумента объект типа largeStruct это дорого, чтобы скопировать. Аргумент может быть передан ссылкой вместо значения.

#include <array>
#include <algorithm>

void init(int& val) { //Noncompliant
    val = 0;
}

typedef struct largeStruct {
    std::array<int,100> arrayOfIntegers;
    int init;
}largeStruct;

largeStruct reset(void) { //Noncompliant
    largeStruct aStruct;
    std::fill(aStruct.arrayOfIntegers.begin(), aStruct.arrayOfIntegers.end(), 0);
    aStruct.init = 0;
    return aStruct;
}

В этом примере, init функций и reset только запишите в содержимое их параметров. Поэтому эти параметры являются выходными параметрами.

  • Функциональный init() с подписью:

    void init(int& val);
    берет в качестве аргумента объект типа int это дешево, чтобы переместиться. Объект может быть возвращен значением вместо того, чтобы быть переданным ссылкой.

  • Функциональный reset() с подписью:

    largeStruct reset(void);
    берет в качестве аргумента объект типа largeStruct это дорого, чтобы переместиться. Объект может быть передан ссылкой вместо того, чтобы быть возвращенным значением.

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

Группа: операторы объявления
Категория: консультация, неавтоматизированная
Введенный в R2021b