emplace
Bu metod C++11 ile geldi. Aynı emplace_back() gibidir. Tek fark olarak yeni nesne en sona değil verilen iterator'den sonra eklenir.
Eğer nesnemiz parametre almıyorsa sadece emplace_back()'i çağırmamız yeterli.
Şöyle yaparız.
Açıklaması şöyle
Örnek
Aşağıdaki kod parçası derlenmez çünkü copy constructor delete edilse bile sağlanıyor ve move constructor'ın üretilmesi engelleniyor.
Aşağıdaki kod parçası derlenmez çünkü copy constructor sağlanmış ancak const değil! Derlenmesi için copy constructor const yapılır veya yapılmak istenmezse move constructor tanımlanır.
Elimimizde şöyle bir kod olsun. Bu kod sorunsuz çalışır.
1. Önce yeni bellek ayrılır
2. emplace_back yeni bellek alanı üzerinde gerçekleşir.
3. Mevcut elemanlar yeni bellek alanına taşınır.
4. Eski bellek silinir.
insert metodu
Açıklaması şöyle. Metod vector'ün boyunu büyütür.
Metodun C++98 imzası şöyledir.
Yeni C++11 ile push_back metodları iki imzaya sahip oldular. Bunlar
move ile çalışan metodun için şuna benzer.
İkinci özelliği ise metodun kullanılmakta olan iterator'leri gerçersiz hale (invalidate) getirmesi.
Burada ilginç bir soru var. Vektör'ün içindeki bir elemanı tekrar push_back() ile eklersek ne olur diye soruyor.
Bu metod C++11 ile geldi. Aynı emplace_back() gibidir. Tek fark olarak yeni nesne en sona değil verilen iterator'den sonra eklenir.
struct Foo
{
Foo(int n, double x);
};
std::vector<Foo> v;
v.emplace(someIterator, 42, 3.1416);
emplace_back metodu
Bu metod C++11 ile geldi. emplace_back() metodu verilen parametreleri alarak, vector'ün kendi içinde bir nesne oluşturur. Yani nesnenin constructor metodunu kullanarak aşağıdaki gibi kod yazmaya gerek kalmaz.v.push_back(Foo(42, 3.1416));
Bunun yerine emplace_back() kullanılır. Elimizde Foo vector'ü olsun. Bu vector'e emplace_back ile şöyle ekleme yaparız.struct Foo
{
Foo(int n, double x);
};
std::vector<Foo> v;
v.emplace_back(42, 3.1416);
std::string için şöyle yaparız.v.emplace_back("some_string");
emplace_back boş çağrılabilirEğer nesnemiz parametre almıyorsa sadece emplace_back()'i çağırmamız yeterli.
v.emplace_back();
emplace_back lvalue için çağrılabilirŞöyle yaparız.
std::string str("some_string");
v.emplace_back(std::move(str));
emplace_back move constructor gerektirirAçıklaması şöyle
In order to emplace into a vector, the element type must be MoveInsertable and MoveAssignable.Emplace metodlarının çalışabilmesi için nesnenin move constructor metodunun olması gerekir. Eğer move constructor sağlamıyorsak veya move constructor üretilmesi engelleniyorsa derleyici hata verir.
Örnek
Aşağıdaki kod parçası derlenmez çünkü copy constructor delete edilse bile sağlanıyor ve move constructor'ın üretilmesi engelleniyor.
class MyType {
public:
MyType(std::array<double, 6> a) {}
MyType(const MyType& that) = delete;
};
int main() {
std::vector<MyType> v;
std::array<double, 6> a = {1,2,3,4,5,6};
v.emplace_back(a);
}
Dolayısıyla şöyle bir move constructor sağlamamız gerekir.MyType(MyType &&a) {/*code*/} //move constructor
ÖrnekAşağıdaki kod parçası derlenmez çünkü copy constructor sağlanmış ancak const değil! Derlenmesi için copy constructor const yapılır veya yapılmak istenmezse move constructor tanımlanır.
struct Vertex
{
Vertex(float pos) { }
Vertex(Vertex& other) { }
};
std::vector<Vertex> arrayOfVertices;
arrayOfVertices.emplace_back(7.f);
emplace_back'in kendi elemanı ile çağrılmasıElimimizde şöyle bir kod olsun. Bu kod sorunsuz çalışır.
std::vector<int> nums{21, 22, 23, 24};
nums.emplace_back(nums[0]);
nums.emplace_back(nums[1]);
for (auto n : nums) {
std::cout << n << std::endl;
}
Kendi elemanımız ile kullandığımız için eğer vector resize olursa elemanda bozulmalar olabilir diye düşünebiliriz. Ancak standart bu durum için şöyle bir çalışma kuralı getiriyor.1. Önce yeni bellek ayrılır
2. emplace_back yeni bellek alanı üzerinde gerçekleşir.
3. Mevcut elemanlar yeni bellek alanına taşınır.
4. Eski bellek silinir.
insert metodu
Açıklaması şöyle. Metod vector'ün boyunu büyütür.
insert metodu vector veri yapısının vermiş olduğu tüm iterator ve reference'ları geçersiz hala getirir.The vector is extended by inserting new elements before the element at the specified position, effectively increasing the container size by the number of elements inserted.This causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity.
Metodun C++98 imzası şöyledir.
void insert (iterator position, size_type n, const value_type& val);
C++11 ile imzası ise şöyleiterator insert(const_iterator position, const T& x);
iterator insert(const_iterator position, T&& x);
Iterator invalidation rules yazısı durumu özetliyor.push_back metoduall iterators and references before the point of insertion are unaffected, unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)
Yeni C++11 ile push_back metodları iki imzaya sahip oldular. Bunlar
vector<T>::push_back(const T&);
ve move işlemi ile çalışanvector<T>::push_back(T&&);
metodları.move ile çalışan metodun için şuna benzer.
void push_back( Object && x )
{
if( theSize == theCapacity )
reserve( 2 * theCapacity + 1 );
objects[ theSize++ ] = std::move( x );
}
Bu metodun iki tane önemli özelliği var. Birinci özelliği metoda geçilen parametrenin kopyasını alınır.Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.
Burada ilginç bir soru var. Vektör'ün içindeki bir elemanı tekrar push_back() ile eklersek ne olur diye soruyor.
exception
Açıklaması şöyle
Açıklaması şöyle
Açıklaması şöyleIf an exception is thrown (which can be due to Allocator::allocate() or element copy/move constructor/assignment), this function has no effect (strong exception guarantee).
So in case of failure, the last push_back which caused the exception will be rolled back, but everything else will be fine: your vector will contain all of the previously pushed elements, and will be in a consistent state.Elimizde şöyle bir kod olsun. Eğer push_back exception atarsa v exception fırlatan en son push_back işleminden önceki halinde kalır.
std::vector<int> v;
try {
for(unsigned int i = 0; i < desiredSize; ++i)
v.push_back(i);
}
catch (const std::bad_alloc&) {
cerr << "Out of memory! v.size() = " << v.size() << endl;
}
Hiç yorum yok:
Yorum Gönder