c ++ оптимально возвращает структуры и векторы - PullRequest
2 голосов
/ 29 октября 2019

Я читаю много разных вещей по оптимизации C ++, и я довольно запутался. Буду признателен за помощь. По сути, я хочу уточнить, что должно быть указателем или нет, когда я передаю векторы и структуры в качестве параметров или возвращаю векторы и структуры.

Скажем, у меня есть структура, которая содержит 2 элемента: int и затемвектор целых чисел. Я буду создавать эту структуру локально в функции, а затем возвращать ее. Эта функция будет вызываться несколько раз и каждый раз генерировать новую структуру. Я хотел бы сохранить последнюю структуру, созданную в члене класса (например, lastStruct_). Поэтому перед возвратом структуры я мог бы каким-то образом обновить lastStruct_.

Теперь, что было бы лучшим способом сделать это, зная, что вектор в структуре может быть довольно большим (нужно будет избегать копий). Вектор в структуре должен быть указателем? Если я хочу поделиться lastStruct_ с другими классами, создав метод get_lastStruct (), должен ли я возвращать ссылку на lastStruct_, указатель или не заботиться об этом? Должен ли lastStruct_ быть общим указателем?

Это меня довольно смущает, потому что, очевидно, C ++ знает, как избежать копирования, но я также вижу, что многие люди рекомендуют использовать указатели, в то время как другие говорят, что указатель на вектор не имеет никакого смысла.

struct MyStruct {
    std::vector<int> pixels;
    int foo;
}

class MyClass {
    MyStruct lastStruct_;
public:
    MyStruct create_struct();
    MyStruct getLastStruct();
}

MyClass::create_struct()
{
    MyStruct s = {std::vector<int>(100, 1), 1234};
    lastStruct_ = s;
    return s;
}

MyClass::getLastStruct()
{
    return lastStruct_;
}

1 Ответ

3 голосов
/ 29 октября 2019

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

Почему? Две вещи. Оптимизация возвращаемого значения (RVO / NRVO) устранит необходимость в временных расходах при возврате. Этого достаточно для почти всех случаев.

Когда оптимизация возвращаемого значения не применяется, семантика перемещения будет. возвращение именованной переменной (например: return my_struct;) приведет к неявному перемещению в случае, если NRVO не будет применяться.

Так почему же он всегда быстрее разделяемого указателя? Поскольку при копировании общего указателя необходимо разыменовать управляющий блок, чтобы увеличить количество владельцев. А поскольку это атомарная операция, приращение не является бесплатным.

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


Теперь, когда вы добавили код, стало гораздо понятнее, что вы пытаетесь сделать.

Здесь нет возможности обойти копию. Если вы измеряете снижение производительности, то решение может содержать std::shared_ptr<const std::vector<int>>, поскольку вы сохраните значение семантическим, но избежите векторного копирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...