Expensive pass by value

Возможно, параметр дорого копируется

Описание

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

  • Параметр является нетривиально копируемым типом. Для получения дополнительной информации о нетривиально копируемых типах см. 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*) для кода С или к ссылке const (const&) для кода С++.

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

Примеры

расширить все

#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 который передается по значению и приводит к дорогостоящей копии.

Коррекция - прохождение большого Struct по 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++
По умолчанию: Off
Синтаксис командной строки : EXPENSIVE_PASS_BY_VALUE
Влияние: Средний
Введенный в R2020b