Using Vector with Move-Only Types

Can I use std::vector with move-only types like std::unique_ptr?

Yes, you can use std::vector with move-only types like std::unique_ptr. However, there are some important considerations and best practices to keep in mind.

Basic Usage

Here's a simple example of using std::vector with std::unique_ptr:

#include <iostream>
#include <vector>
#include <memory>

class Resource {
public:
  Resource(int id) : id(id){
    std::cout << "Resource " << id <<
      " created\n";
  }

  ~Resource(){
    std::cout << "Resource " << id <<
      " destroyed\n";
  }

  int getId() const{ return id; }

private:
  int id;
};

int main(){
  std::vector<std::unique_ptr<Resource>>
    resources;

  // Adding elements
  resources.push_back(
    std::make_unique<Resource>(1)); 
  resources.emplace_back(
    std::make_unique<Resource>(
      2)); // Accessing elements
  for (const auto& resource : resources) {
    std::cout << "Resource ID: "
      << resource->getId() << '\n';
  }

  // Vector will automatically delete the 
  // Resources when it goes out of scope
}
Resource 1 created
Resource 2 created
Resource ID: 1
Resource ID: 2
Resource 2 destroyed
Resource 1 destroyed

Considerations

  1. Use std::move() with the emplace_back() or push_back() methods: Since std::unique_ptr is move-only, you need to use emplace_back() or push_back() with std::move() to add elements.
  2. Avoid copy operations: std::vector may need to reallocate and move its elements when it grows. Ensure your move-only types have efficient move constructors and move assignment operators.
  3. Be cautious with reallocation: When std::vector reallocates, it moves all its elements. This is fine for std::unique_ptr, but could be problematic for other move-only types that have side effects when moved.
  4. Be careful with algorithms: Some standard algorithms may not work with move-only types. Always check the requirements of algorithms you plan to use.

Additionally, to minimize reallocations, consider using reserve() if you know how many elements you'll be adding:

std::vector<std::unique_ptr<Resource>> resources;

// Prepare space for 10 elements
resources.reserve(10);

Example with Custom Move-Only Type

Here's an example with a custom move-only type:

#include <iostream>
#include <vector>
#include <utility>

class MoveOnlyType {
public:
  MoveOnlyType(int value) : value(value){
    std::cout << "MoveOnlyType " << value <<
      " created\n";
  }

  MoveOnlyType(const MoveOnlyType&) = delete;
  MoveOnlyType& operator=(const MoveOnlyType&)
  = delete;

  MoveOnlyType(MoveOnlyType&& other) noexcept
    : value(other.value){
    std::cout << "MoveOnlyType " << value <<
      " moved\n";
    other.value = 0;
  }

  MoveOnlyType& operator=(
    MoveOnlyType&& other) noexcept{
    if (this != &other) {
      value = other.value;
      other.value = 0;
      std::cout << "MoveOnlyType " << value
        << " move assigned\n";
    }
    return *this;
  }

  ~MoveOnlyType(){
    std::cout << "MoveOnlyType " << value <<
      " destroyed\n";
  }

  int getValue() const{ return value; }

private:
  int value;
};

int main(){
  std::vector<MoveOnlyType> vec;
  vec.reserve(3);
  // Avoid reallocation for this example

  vec.push_back(MoveOnlyType(1));
  vec.emplace_back(2);
  vec.push_back(std::move(MoveOnlyType(3)));

  for (const auto& item : vec) {
    std::cout << "Value: " << item.getValue() <<
      '\n';
  }
}
MoveOnlyType 1 created
MoveOnlyType 1 moved
MoveOnlyType 0 destroyed
MoveOnlyType 2 created
MoveOnlyType 3 created
MoveOnlyType 3 moved
MoveOnlyType 0 destroyed
Value: 1
Value: 2
Value: 3
MoveOnlyType 1 destroyed
MoveOnlyType 2 destroyed
MoveOnlyType 3 destroyed

This example demonstrates creating, moving, and destroying move-only objects within a std::vector. Understanding these concepts is crucial when working with move-only types in containers like std::vector.

Dynamic Arrays using std::vector

Explore the fundamentals of dynamic arrays with an introduction to std::vector

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Storing Polymorphic Types in std::vector
How can I store polymorphic types in a std::vector?
Removing Objects from std::vector
How can I remove objects from a std::vector?
Removing Elements from the Middle of a Vector
How can I efficiently remove elements from the middle of a std::vector?
Implementing a Circular Buffer with Vector
How do I implement a circular buffer using std::vector?
Thread Safety with std::vector
How can I safely access std::vector elements in a multithreaded environment?
Using Vector for a 2D Grid
How can I use std::vector to implement a simple 2D grid or matrix?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant