Expensive pass by value

Параметр может быть дорогим, чтобы скопировать

Описание

Этот дефект происходит, когда вы передаете параметр значением вместо ссылкой или указателем, но параметр не модифицирован и также:

  • Параметр является нетривиально copyable типом. Для больше на нетривиально copyable типах, см. is_trivially_copyable.

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

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

Polyspace не повышает дефекта если:

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

  • Переданный параметром, передаваемым по значению изменяется.

Например, никакой дефект не повышен в этом коде где большой тривиально copyable 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 отмечает параметр функции метода set setName который передается значением и результатами в дорогой копии. Тип std::string не тривиально copyable. Переданный параметром, передаваемым по значению setRank не отмечается потому что size_t маленький тривиально copyable тип.

Коррекция — передает 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