exponenta event banner

Дорогой проход по стоимости

Параметр может быть дорогостоящим для копирования

Описание

Этот дефект возникает при передаче параметра по значению, а не по ссылке или указателю, но параметр не изменяется и либо:

  • Параметр является нетривиально копируемым типом. Дополнительные сведения о нетривиально копируемых типах см. в разделе is_trivially_copyable.

  • Параметр является тривиально копируемым типом, который превышает определенный размер. Например, объект больше 2 * sizeof(void *) дороже для передачи по значению, чем по ссылке или указателю.

Polyspace ® помечает немодифицированные параметры, удовлетворяющие предыдущим условиям, даже если параметры не объявленыconst.

Polyspace не вызывает дефектов, если:

  • Переданный параметр значения является типом только для перемещения. Например, std::unique_ptr может быть перемещен из, но не может быть скопирован.

  • Параметр переданного значения изменяется.

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

#include<memory>

typedef struct Buffer {
    unsigned char bytes[ 20 ];
} Buffer;


void func1(Buffer modified_param)
{
    ++modified_param.bytes[ 0 ];
}

void func2(std::unique_ptr<Buffer> move_only_param);

Риск

Передача параметра по значению создает копию параметра, который неэффективен, если параметр дорого копировать. const& или const* в сигнатуре функции и непреднамеренно запустить неэффективную версию функции.

Зафиксировать

Преобразовать параметр в указатель const (const*) для кода C или для ссылки const (const&) для кода C++.

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

Примеры

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

#include<string>

class Player
{
public:
    void setName(std::string const str)
    {
        name = str;
    }
    void setRank(size_t r)
    {
        rank = r;
    }
    // getter functions implementation
private:
    std::string name;
    size_t rank;

};

В этом примере Polyspace помечает параметр функции setter setName который передается по стоимости и приводит к дорогостоящей копии. тип std::string не является тривиально копируемым. Переданный по параметру значения setRank не помечен, потому что size_t является небольшим тривиально копируемым типом.

Коррекция - проход std::string Параметр по const Ссылка

Чтобы избежать неэффективной операции копирования, используйте const& для передачи параметра.

#include<string>

class Player
{
public:
    void set_name(std::string const& s)
    {
        name = s;
    }
    void set_rank(size_t r)
    {
        rank = r;
    }
    // getter functions implementation
private:
    std::string name;
    size_t rank;

};
#include<stdio.h>
#include<string.h>

typedef struct _Player {
    char name[50];
    size_t rank;
} Player;


void printPlayer(Player const player)
{

    printf("Player name: %s\n", player.name);
    printf("Player rank: %zu\n", player.rank);
}

В этом примере Polyspace помечает параметр printPlayer который передается по значению и приводит к дорогостоящей копии.

Коррекция - прохождение большой структуры по const Указатель

Чтобы избежать неэффективной операции копирования, используйте const* для передачи параметра, затем используйте соответствующую нотацию для считывания элементов структуры.

#include<stdio.h>
#include<string.h>

typedef struct _Player {
    char name[50];
    size_t rank;
} Player;


void printPlayer(Player const* player)
{

    printf("Player name: %s\n", player->name);
    printf("Player rank: %zu\n", player->rank);
}

Информация о результатах

Группа: Производительность
Язык: C | C++
По умолчанию: Откл.
Синтаксис командной строки: EXPENSIVE_PASS_BY_VALUE
Воздействие: среднее
Представлен в R2020b