Есть ли в C++ аналог функций emplace/emplace_back в C++ 11?
Начиная с C++11, можно написать что-то вроде
#include <vector>
#include <string>
struct S
{
S(int x, const std::string& s)
: x(x)
, s(s)
{
}
int x;
std::string s;
};
// ...
std::vector<S> v;
// add new object to the vector v
// only parameters of added object's constructor are passed to the function
v.emplace_back(1, "t");
Есть ли C# аналог функций C++, таких как emplace
или же emplace_back
для контейнерных классов (System.Collections.Generic.List
)?
Обновление: в C# подобный код может быть написан как list.EmplaceBack(1, "t");
вместо list.Add(new S(1, "t"));
, Было бы неплохо не запомнить имя класса и написать new ClassName
в таких ситуациях каждый раз.
4 ответа
Вы можете немного улучшить вариант @Boo с расширением.
Вы можете создать экземпляр объекта с помощью Activator.CreateInstance, чтобы сделать решение более общим.
public static class ListExtension
{
public static void Emplace<S>(this IList<S> list, params object[] parameters)
{
list.Add((S)Activator.CreateInstance(typeof(S), parameters));
}
}
Примечание: не проверены параметры типа и количества, поэтому, если вы что-то делаете неправильно, вы получаете ошибки только во время выполнения
В общем, в C# нет ничего похожего, и его потребность намного меньше, чем в C++.
В C#, когда у вас есть List<SomeReferenceType>
что у вас есть List<ReferenceToSomeType>
Итак, список ссылок с размером каждого элемента 4 или 8 байт (см. Насколько велика ссылка на объект в.NET?). Копирование ссылки не приводит к дублированию базового объекта, поэтому это очень быстро (вы копируете около 4 или 8 байт, и процессор оптимизирован для этой операции, потому что это размер собственного указателя процессора). Итак, когда вы someList.Add(someReference)
что вы делаете, это добавление ссылки на ваш List<>
,
В C++, когда у вас есть std::vector<SomeType>
что у вас есть вектор SomeType
с размером каждого элемента, равным sizeof(SomeType)
, Вставка нового элемента в std::vector<>
приведет к дублированию вставляемого элемента (клонированный, скопированный... выберите понравившийся глагол). Это дорогая операция.
Довольно часто используемый вами шаблон заключается в том, что вы создаете объект, просто чтобы вставить его в std::vector<>
, Чтобы оптимизировать эту операцию в C++11, они добавили два способа сделать это: std::vector<>::emplace
метод и поддержка со стороны std::vector<>
ход семантический. Разница в том, что семантика перемещения должна поддерживаться SomeType
тип (вам нужен конструктор перемещения с noexcept
спецификатор), в то время как каждый тип поддерживает emplace
(что в итоге просто использовал конструктор размещения).
В C# вы можете использовать метод расширения, чтобы достичь того, что вы хотите
public static class ListExtension
{
public static void Emplace(this IList<S> list, int x, string s)
{
list.Add(new S(x, s));
}
}
затем используйте это так
myList.Emplace(1,"t");
Кажется, у вас есть следующие проблемы:
- Это больше, чтобы набрать по
"new S"
, Но"add"
короче чем"emplace"
, Тип добавляется для вас intellisense (просто нажмите Enter после ввода"new "
):
Вы боитесь писать неправильный тип. Ну, вы не можете с
List<T>
, Intellisense поможет вам печатать, а компилятор не допустит добавления неправильного типа во время компиляции.Производительность: см. Ответ @Xanatos.
list.Add(new S(1, "t"));
идеально подходит для использования.
Вывод: нам не нужно emplace
в C#
,