cFx
cFx

Reputation: 67

getting error on vector<unique_ptr<X>> v

I´m quiet new on C++ and currently learning to understand smart pointers.Therefore I`m currently working on a little console-program for inserting,searching and deleting songs ... for learning purposes to get used to the stuff =)

Here is my code:

Song.hpp

#pragma once
#include <vector>
#include <memory>
#include <string>

class Song
{

public:
    typedef std::unique_ptr<Song> pSong;

public:
    Song();
    ~Song();
    void setTitle(std::string title);
    void setArtist(std::string artist);
    void checkSong(std::string item, int iterator);
    void get();

private:
    std::string _title;
    std::string _artist;
};

Song.cpp

#include "Song.hpp"
#include <iostream>



Song::Song()
{
}


Song::~Song()
{
}

void Song::setTitle(std::string title)
{
    _title = title;
}

void Song::setArtist(std::string artist)
{
    _artist = artist;
}

void Song::checkSong(std::string item, int iterator)
{
    if (_artist == item || _title == item)
    {
        std::cout << "Item found on Slot: " << iterator << std::endl;
    }
    else 
    {
        std::cout << "No item found!" << std::endl;
    }
}

void Song::get()
{
    std::cout << _artist << " - " << _title << std::endl;
}

Main.cpp

#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
#include "Song.hpp"

//prototype
void IntVector();
void SongVector();
Song* setSong(std::string title, std::string artist);
void find(std::string item, std::vector<Song::pSong> v);


std::vector<Song::pSong> SongList;

int main()
{
    int k;
    SongVector();
    std::cin >> k;
    return 0;
}

void IntVector()
{
    // Create Vector
    std::vector<std::unique_ptr<int>> v;

    // Create a few unique_ptr<int> instances and fill them with ints
    v.push_back(std::unique_ptr<int>(new int(30)));
    v.push_back(std::unique_ptr<int>(new int(600)));
    v.push_back(std::unique_ptr<int>(new int(200)));
    v.push_back(std::unique_ptr<int>(new int(20)));
    v.push_back(std::unique_ptr<int>(new int(200)));
    v.push_back(std::unique_ptr<int>(new int(160)));
    v.push_back(std::unique_ptr<int>(new int(4)));
    v.push_back(std::unique_ptr<int>(new int(5)));
    v.push_back(std::unique_ptr<int>(new int(315)));


    // define vector<int> for storing values of the unique_ptr
    std::vector<int> intList;

    for (int i = 0; i < v.size(); i++)
    {
        // get memory-adress of each element
        auto result = v[i].get();
        // store value of result-pointer in Vector
        intList.push_back(*result);
        std::cout << *result << std::endl;
    }

    // Sort int of new Vector
    std::sort(intList.begin(), intList.end());

    // Loop through intList and cout
    for (int i = 0; i < intList.size(); i++)
    {
        std::cout << intList[i] << std::endl;
    }

}

void SongVector()
{

    Song* first = setSong("Afroki","Steve Aoki");
    Song* secound = setSong("Hype", "Steve Aoki");
    Song* third = setSong("Madness", "Steve Aoki");
    Song* fourth = setSong("Cake Face", "Steve Aoki");
    SongList.push_back(Song::pSong(first));
    SongList.push_back(Song::pSong(secound));
    SongList.push_back(Song::pSong(third));
    SongList.push_back(Song::pSong(fourth));

    for (const auto& song : SongList)
    {
        song->get();
    }

    find("Madness", SongList);
}

Song* setSong(std::string title, std::string artist)
{
    Song* song = nullptr;
    song = new Song;
    song->setArtist(artist);
    song->setTitle(title);
    return song;
}


void find(std::string item, std::vector<Song::pSong> v)
{

    int i = 0;
    for (const auto& song : v)
    {
        song->checkSong(item,i);
        i++;
    }
}

I got following error:

std::unique_ptr<Song,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
1>          with
1>          [
1>              _Ty=Song
1>          ]

I found out, that this error only occurs, when calling my find(...)-method, so I´m guessing that somewhere in there is my mistake, but I just cant find out, what Ive done wrong. Would appreciate your help.

Upvotes: 0

Views: 466

Answers (2)

Slava
Slava

Reputation: 44248

std::unique_ptr provide unique ownership (hense the name) which means beside other you cannot copy instance of std::unique_ptr - which would mean shared ownership. When you passing std::vector<std::unique_ptr<whatever>> by value you creating a copy of vector instance, which tries to copy each element. So simplest solution would be to pass std::vector instance by const reference (as you do not have intention to modify vector):

void find( const std::string &item, const std::vector<Song::pSong>& v);

beside fixing your problem passing by (const) reference is more efficient for non trivial objects, so you can also use it for std::string

in your intVector() function:

for (int i = 0; i < v.size(); i++)
    {
        // get memory-adress of each element
        auto result = v[i].get();
        // store value of result-pointer in Vector
        intList.push_back(*result);           
        std::cout << *result << std::endl;
     }

you do not really need to get raw pointer, just use std::unique_ptr itself:

for (int i = 0; i < v.size(); i++)
{
    // get smart pointer for each element
    const auto &result = v[i];
    // store value of result-pointer in Vector
    intList.push_back(*result);
    std::cout << *result << std::endl;
}

Upvotes: 4

Tarik Neaj
Tarik Neaj

Reputation: 548

void find(std::string item, std::vector<Song::pSong> v)

You need to pass vectors by reference. Add &.

void find(std::string item, std::vector<Song::pSong>& v)

Don't forget to also change the prototype of the function.

Upvotes: 1

Related Questions