0

I've write one simple C++ program to test the smart pointer, but I've found that the smart pointer affect the memory leak issue. Please see below code for it:

test.cpp: (have tested it in the CLANG 7.0 or gcc 7.3.0)

#include <bits/stdc++.h>

using namespace std;

class Date {
private:
  int day = 0, month = 0, year = 0;
  string dateInString;

public:
  Date() { cout << "Date Constructor:" << *this << endl; }

  Date(int inMonth, int inDay, int inYear)
    : day(inDay), month(inMonth), year(inYear)
  {
    cout << "Date Constructor: " << *this << ends;
    DisplayDate();
  }

  Date(const Date &copySource)
  {
    cout << "Date Copy Constructor." << *this << endl;
    day   = copySource.day;
    month = copySource.month;
    year  = copySource.year;
  }

  Date(Date &&moveSource)
  {
    cout << "Date Move Constructor." << *this << endl;
    day   = moveSource.day;
    month = moveSource.month;
    year  = moveSource.year;
  }

  virtual ~Date() { cout << "Date Destructor: " << *this << endl; }

  const Date &operator=(const Date &copySource)
  {
    cout << "Date Assignment Operator=" << *this << endl;
    if (this != &copySource) {
      day   = copySource.day;
      month = copySource.month;
      year  = copySource.year;
    }
    return *this;
  }

  operator const char *()
  {
    // assists string construction
    ostringstream formattedDate;
    formattedDate << month << "/" << day << "/" << year;
    dateInString = formattedDate.str();
    return dateInString.c_str();
  }

  void DisplayDate() { cout << month << "/" << day << "/" << year << endl; }

  // prefix increment
  Date &operator++()
  {
    ++day;
    return *this;
  }

  // prefix decrement
  Date &operator--()
  {
    --day;
    return *this;
  }

  // postfix increment
  Date operator++(int postfix)
  {
    Date copy(month, day, year);
    ++day;
    // copy of instance increment returned
    return copy;
  }

  // postfix decrement
  Date operator--(int postfix)
  {
    cout << "operator--" << endl;
    auto p = make_unique<Date>(month, day, year);
    // auto p = new Date(month, day, year);
    --day;
    // copy of instance increment returned
    return *p;
  }
};

auto main() -> decltype(0)
{
  Date holiday(12, 25, 2016);

  Date postfixDay1;
  postfixDay1 = holiday--;
  cout << "holiday after a postfix-decrement is : ";
  holiday.DisplayDate();

  cout << "postfixDay1 after a postfix-decrement is : ";
  postfixDay1.DisplayDate();

  return 0;
}

The program will output below message:

Date Constructor: 12/25/2016 12/25/2016
Date Constructor:0/0/0
operator--
Date Constructor: 12/25/2016 12/25/2016
Date Copy Constructor.0/0/0
Date Destructor: 12/25/2016
Date Assignment Operator=0/0/0
Date Destructor: 12/25/2016
holiday after a postfix-decrement is : 12/24/2016
postfixDay1 after a postfix-decrement is : 12/25/2016
Date Destructor: 12/25/2016
Date Destructor: 12/24/2016

Summary: We can found that there are three constructor invoked on, but there are four destructor invoked on! it means that the smart pointer has been destructored twice.

Why the smart pointer can't handle this case?

Deduplicator
  • 41,806
  • 6
  • 61
  • 104
  • 3
    There are 4 constructor calls (1 copy ctor) – hansmaad Mar 05 '18 at 07:26
  • You don't need the custom copy constructor, move constructor, or even the overloaded assignment operator method. These methods are only needed when memberwise assignment would do something you likely don't want (e.g. share a pointer). – selbie Mar 05 '18 at 07:27
  • 1
    Please take some time to read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Some programmer dude Mar 05 '18 at 07:32
  • Oh and your `const char*` conversion operator will lead to *undefined behavior* as you return a pointer to data in an object that is immediately destructed. – Some programmer dude Mar 05 '18 at 07:33
  • And why do you use smart pointers in the way you do? What is the reason behind that? What is the problem that is supposed to solve? I don't see anything that warrants the use of a smart pointer in your postfix `operator--` function. – Some programmer dude Mar 05 '18 at 07:35
  • Lastly, why do you use `auto main() -> decltype(0)` instead of `auto main() -> int` (or the more traditional `int main()`)? And you don't use trailing return types anywhere else? What's with the inconsistency? – Some programmer dude Mar 05 '18 at 07:37
  • Yes, you are right:) Thank you very much. – Kenneth Zheng Mar 05 '18 at 07:39
  • `auto main() -> decltype(0)` I have a lot to learn about C++. I know it's off topic, but could someone explain what that is? – john Mar 05 '18 at 07:51
  • Hmm, trailing return type. Never seen that before. – john Mar 05 '18 at 07:52
  • 1
    @john More commonly used for template functions and lambdas. – super Mar 05 '18 at 07:53

0 Answers0