#c
#c
Вопрос:
Допустим, мне нужно вызвать код в API, которым я не владею. Указанный код принимает некоторые параметры только по значению. Пример:
class PleaseUseReferences
{
void DoSometing(VectorFloat passedByValue);
}
на стороне вызова я должен теперь сделать либо:
PleaseUseReferences pus;
pus.DoSometing(VectorFloat(0.0f,0.0f,0.0f));
или
PleaseUseReferences pus;
VectorFloat unnecessaryTemporary(0.0f,0.0f,0.0f);
pus.DoSometing(unnecessaryTemporary);
в любом случае я получаю два вызова конструктора. Один на стороне вызывающей стороны, а затем другой конструктор копирования для аргумента, который был передан по значению.
С пониманием того, что
- Я не могу изменить API, который был мне предоставлен, и я не могу изменить содержащийся в нем код.
- Я знаю, что временное бесполезно после вызова.
Есть ли способ сэкономить на этом первом вызове конструктора?
В приглашении от @cigien я опробовал два сценария.
Вот код, который я использовал, он демонстрирует, о чем говорил @cigien :
// Example program
#include <iostream>
#include <string>
class Vector
{
public:
Vector(int x, int y)
{
printf("nConstructor");
m_x = x;
m_y = y;
}
Vector(const Vectoramp; other)
{
printf("nCopy Constructor");
m_x = other.m_x;
m_y = other.m_y;
}
static void HorriblePrint(Vector v)
{
printf("nx : %d y : %d", v.m_x , v.m_y);
}
int m_x,m_y;
};
int main()
{
printf("nWith Temporary");
printf("n****************");
Vector v(0,0);
Vector::HorriblePrint(v);
printf("n****************");
printf("nnnWithout Temporary");
printf("n****************");
Vector::HorriblePrint(Vector(1,1));
printf("n****************");
}
Вот результат
With Temporary
****************
Constructor
Copy Constructor
x : 0 y : 0
****************
Without Temporary
****************
Constructor
x : 1 y : 1
****************
Комментарии:
1. Не должно быть никаких копий, с
pus.DoSometing(VectorFloat(0.0f,0.0f,0.0f));
которыми это должно справиться.2. Что заставляет вас думать, что вызов конструктора занимает значительное количество времени?
3. Я просто использовал VectorFloat в качестве примера. В реальном варианте использования, который я рассматриваю, конструктор значительно сложнее @Sneftel
4. ^ обе эти точки. Оптимизация компилятора должна предотвращать две копии, и выполнение копии, вероятно, в любом случае займет незначительное количество времени. Скажите, вы сначала измерили?
5. В первом примере, использующем a temporary, даже не будет копий без оптимизации компилятора. Предположение не доказано.
Ответ №1:
в любом случае я получаю два вызова конструктора. Один на стороне вызывающей стороны, а затем другой конструктор копирования для аргумента, который был передан по значению.
Не обязательно. Например:
- Если тело метода доступно как часть той же единицы преобразования, весь вызов может быть пропущен.
- Если включена оптимизация времени соединения, то снова функция может быть исключена.
- Начиная с C 17, в стандарте C , похоже, есть формулировка об исключении копирования анонимных временных файлов. Хотя я не уверен в этом на 100%, и это может зависеть от ABI.
Кроме того, помните, что «преждевременная оптимизация — корень всего зла». Вероятно, более важно, чтобы эта часть вашего кода была читаемой и поддерживаемой. Я предполагаю, что 3-сторонний API не будет вызывать дорогостоящее копирование какого-либо большого объекта.
Комментарии:
1. На самом деле, это не » исключение копирования анонимных временных файлов». Нет временного исключения даже из c 17. Вместо этого аргумент является значением prvalue, которое материализуется только там, где это необходимо. И я думаю, что это относится к случаю OP.
2. «Я предполагаю, что 3-й сторонний API не заставит дорогостоящее копирование какого-либо большого объекта». Можно было бы надеяться. К сожалению, здесь это не так.
3. @Vidrohi Есть ли у типа API конструктор перемещения?
4. @Caleth Это не так, но предположим, что это так? (Кажется, вам есть чем поделиться, и мне любопытно)
5. @Vidrohi если ни один из конструкторов копирования или перемещения или присваивания не объявлен, он неявно сгенерирован. Перемещение вектора — это несколько манипуляций с указателем, независимо от количества элементов