-1

I'm trying to convert written code used by shared_ptr to unique_ptr because in the code of its usage seems shared_ptr unnecessary and it will be an exercise with smart pointers. As far as I can detect with debugger the problem is on v.at(i)->push_back(t);. So, as soon as a value entered, the program crashes.

Working code with shared_ptr:

#include <iostream>
#include <iomanip>
#include <memory> // For smart pointers
#include <vector> // For vector container
#include <locale> // For toupper()
using std::vector;
using std::shared_ptr;
int main()
{
    vector <shared_ptr<vector<double>>>records; // Temperature records by days
    size_t day{ 1 }; // Day number
    char answer{}; // Response to prompt
    double t{}; // A temperature
    while (true) // Collect temperatures by day
    { // Vector to store current day's temperatures created on the heap
        auto pDay = std::make_shared<vector<double>>();
        records.push_back(pDay); // Save pointer in records vector
        std::cout << "Enter the temperatures for day " << day++
            << " separated by spaces. Enter 1000 to end:\n";
        while (true)
        { // Get temperatures for current day
            std::cin >> t;
            if (t == 1000.0) break;
            pDay->push_back(t);
        }
        std::cout << "Enter another day's temperatures (Y or N)? ";
        std::cin >> answer;
        if (toupper(answer) == 'N') break;
    }
    double total{};
    size_t count{};
    day = 1;
    std::cout << std::fixed << std::setprecision(2) << std::endl;
    for (auto record : records)
    {
        std::cout << "\nTemperatures for day " << day++ << ":\n";
        for (auto temp : *record)
        {
            total += temp;
            std::cout << std::setw(6) << temp;
            if (++count % 5 == 0) std::cout << std::endl;
        }
        std::cout << "\nAverage temperature: " << total / count << std::endl;
        total = 0.0;
        count = 0;
    }
}

Output:

23 34 29 36 1000
Enter another day's temperatures (Y or N)? y
Enter the temperatures for day 2 separated by spaces. Enter 1000 to end:
34 35 45 43 44 40 37 35 1000
Enter another day's temperatures (Y or N)? y
Enter the temperatures for day 3 separated by spaces. Enter 1000 to end:
44 56 57 45 44 32 28 1000
Enter another day's temperatures (Y or N)? n

Temperatures for day 1:
23.00 34.00 29.00 36.00
Average temperature: 30.50

Temperatures for day 2:
34.00 35.00 45.00 43.00 44.00
40.00 37.00 35.00
Average temperature: 39.13

Temperatures for day 3:
44.00 56.00 57.00 45.00 44.00
32.00 28.00
Average temperature: 43.71

The converted code with unique_ptr:

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

using std::vector;


int main()
{ // Function scope starts here

    // a vector(outside) holding unique_ptrs to a vector(inside) which type is double
    vector<std::unique_ptr<vector<double>>> v;
    size_t day{ 1 };
    char answer{};
    double t{};


    while (true)
    {
        size_t i{};
        auto pDay = std::unique_ptr<vector<double>>();
        v.push_back(std::move(pDay));

        std::cout << "Enter the temperatures for day " << day++
            << " separated by spaces. Enter 1000 to end:\n";

        while (true)
        {
            std::cin >> t;
            if (t >= 1000.0) break;
            v.at(i)->push_back(t);
            ++i;
        }

        //std::cout << v.at(0)->at(0) << std::endl;
        std::cout << "Enter another day's temperatures (Y or N)? ";
        std::cin >> answer;
        if (toupper(answer) == 'N') break;
    }

    double total{};
    size_t count{};
    day = 1;
    std::cout << std::fixed << std::setprecision(2) << std::endl;

    for (auto const& record : v)
    {
        std::cout << "\nTemperatures for day " << day++ << ":\n";
        for (auto temp : *record)
        {
            total += temp;
            std::cout << std::setw(6) << temp;
            if (++count % 5 == 0) std::cout << std::endl;
        }
        std::cout << "\nAverage temperature: " << total / count << std::endl;
        total = 0.0;
        count = 0;
    }

} // Function scope ends here

enter image description here

  • 4
    Please provide a [mcve], and don't include images of text! As you try and reduce the problem space, the issue should become much more obvious to you. – Barry Oct 01 '16 at 17:26
  • This is not minimal. – Lightness Races in Orbit Oct 01 '16 at 17:26
  • 3
    A unique_ptr> is an anti-pattern. (same for the nested vector) –  Oct 01 '16 at 17:27
  • @DieterLücking - why is a nested vector an anti-pattern? (In general, as I suppose you're saying, not w.r.t. this question.) – davidbak Oct 01 '16 at 17:28
  • I could cut off the code from for loops and above variable definitions but I think you might would like to see `foreach` loops whether doing copy, despite of not. – Soner from The Ottoman Empire Oct 01 '16 at 17:30
  • @snr if you think the problem is the `push_back`, then create an example that just does `push_back` and still crashes. – Ryan Haining Oct 01 '16 at 17:34
  • 1
    @davidbak, the anti-pattern is to have a `std::unique_ptr` for a `std::vector`, since vectors can be moved (same efficiency of moving the `unique_ptr`) and are dynamically sized (no need to manually allocate it when needed). Nested vectors can be accomplished with `std::vector>`, which is simpler and easier to use, without any real drawbacks in comparison to `std::vector>>`. – André Sassi Oct 01 '16 at 18:16
  • can you explain more about antipatterns? And, why they are anti-pattern? @DieterLücking – Soner from The Ottoman Empire Oct 01 '16 at 20:40
  • @snr Putting a hand on a hot stove is an anti-pattern, explain it! –  Oct 01 '16 at 20:44

1 Answers1

1

Your std::unique_ptr<std::vector<double>> doesn't point at anything. You'd need to initialize it with a pointer to a vector.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380