复制动态分配数组的构造函数

Copy Constructor for dynamically allocated array

本文关键字:构造函数 数组 动态分配 复制      更新时间:2023-10-16

试图熟悉"3 法则",但我无法让复制构造函数工作。其中一个类私有成员返回 0,而它的值应为 3。

我不确定为什么在执行复制构造函数时,向该类私有成员提供值 0。有问题的成员是theSize,它通过类.cpp中的size()函数返回。

类.h

class Catalog {
public:
    Catalog (int maxCapacity = 100)
    int size() const;
    int capacity() const;
    void add (Book b);
    Catalog(const Catalog& c);
    ~Catalog();
    Catalog& operator= (constCatalog& c) {
        if (this != &c) {
            delete[] books;
            books = new Book[theCapacity];
            *books = *(c.books);
        }
        return *this;
    }
private:
    Book* books;
    int theCapacity;
    int theSize;
};

类.cpp

Catalog::Catalog(int maxCapacity) {
    theCapacity = maxCapacity;
    theSize = 0;
    books = new Book[theCapacity];
}
int Catalog::size() const {
    return theSize();
}
int Catalog::capacity() const {
    return theCapacity;
}
void Catalog::add (Book b)
{
    if (theSize < theCapacity || contains(b.getID())) {
        if (theSize == 0) {
            books[0] = b;
            theSize++;
        }
        else {
            if (!contains(b.getID())) {
                int i = theSize;
                for (; i && b < books[i-1]; --i) {
                    books[i] = books[i - 1];
                }
                books[i] = b;
                for (; i; --i) {
                    books[i - 1] = books[i - 1];
                }       
                theSize++;
            }
            else {
                for (int i = 0; i < theSize; ++i) {
                    if (b == books[i]) {
                        books[i] = b;
                    }
                }
            }
        }
        // Debugging only
        /*for (int i = 0; i < theSize; i++) {
            //cout << books[i] << endl;
        }*/
    }
}
bool Catalog::contains(std::string bookID) const
{
    for (int i = 0; i < theSize; ++i)
    {
        if (books[i].getID() == bookID)
            return true;
    }
    return false;
}
Catalog::Catalog(const Catalog& c) {
    books = new Book[c.theSize];
    for (int i = 0; i < c.theSize; i++) {
        books[i] = c.books[i];
}
Catalog::~Catalog() {
    delete[] books;
}

稍后在main中.cpp当我调用c1.size()时,其中c1是另一个函数中return c的结果,该函数通过使用调试器来自复制构造函数,然后转到析构函数。但是,c1.size() 将按0返回,尽管复制构造函数theSize = c.size()在单步执行时的值为 3

书.cpp

using namespace std;

/**
 * Create a book.
 *
 * @param id the Gutenberg ID for this book
 * @param authorInfo the author of the book
 * @param title the title of the book
 */
Book::Book (std::string theId, std::string authorInfo, std::string theTitle)
    : id(theId), authorName(authorInfo), title(theTitle)
{
}

bool Book::operator< (const Book& b) const
{
  return id < b.id;
}

bool Book::operator== (const Book& b) const
{
  return (id == b.id);
}
std::ostream& operator<< (std::ostream& out, const Book& b)
{
  cout << b.getID() << "t"
          << b.getAuthor()  << "t"
          << b.getTitle();
  return out;
}

std::istream& operator>> (std::istream& in, Book& b)
{
  string line;
  getline (in, line);
  if (!in.good())
    return in;
  int tab1 = line.find ("t");
  int tab2 = line.find ("t", tab1+1);
  string id = line.substr(0, tab1);
  string author = line.substr (tab1+1, tab2-tab1-1);
  string title = line.substr(tab2+1);
  b.setID (id);
  b.setAuthor (author);
  b.setTitle (title);
  return in;
}

主.cpp

using namespace std;

Catalog readCatalog(const string& fileName)
{
    Catalog c;
    ifstream in (fileName);
    in >> c;
    in.close();
    return c;
}

Catalog mergeCatalogs (const Catalog& cat1, const Catalog& cat2)
{
    Catalog result (cat1.size() + cat2.size());
    int i = 0;
    int j = 0;
    while (i < cat1.size() && j < cat2.size())
    {
        Book b1 = cat1.get(i);
        Book b2 = cat2.get(j);
        if (b1.getID() < b2.getID())
        {
            result.add(b1);
            ++i;
        }
        else
        {
            result.add(b2);
            ++j;
        }
    }
    while (i < cat1.size())
    {
        result.add(cat1.get(i));
        ++i;
    }
    while (j < cat2.size())
    {
        result.add(cat2.get(j));
        ++j;
    }
    return result;
}

void mergeCatalogFiles (const string& catalogFile1, const string& catalogFile2)
{
    Catalog c1, c2;
    c1 = readCatalog(catalogFile1);
    cout << catalogFile1 << " contained " << c1.size() << " books." << endl;
    c2 = readCatalog(catalogFile2);
    cout << catalogFile2 << " contained " << c2.size() << " books." << endl;
    Catalog c3 = mergeCatalogs (c1, c2);
    cout <<  "Their merge contains " << c3.size() << " books." << endl;
    cout << c3 << flush;
}
int main (int argc, char** argv)
{
    if (argc != 3)
    {
        cerr << "Usage: " << argv[0] <<
                "catalogFile1 catalogFile2" << endl;
        return -1;
    }
    string file1 = argv[1];
    string file2 = argv[2];
    mergeCatalogFiles (file1, file2);
    if (Counted::getCurrentCount() == 0)
    {
        cout << "No memory leak detected." << endl;
        return 0;
    }
    else
    {
        cout << "Memory leak detected: " << Counted::getCurrentCount() << endl;
        return -2;
    }
}

遵循零法则:使用 std::vector<Book> 替换数组指针和大小。

您的容量是大小的限制。

当达到容量时。 使用相等的范围查找插入位置,替换最后一个元素,然后 std 旋转。

在同一类中管理资源和业务逻辑很容易出错。 一次做一件事。

尝试更多类似的东西:

class Catalog
{
public:
    Catalog (int maxCapacity = 100);
    Catalog(const Catalog& c);
    ~Catalog();
    int size() const;
    int capacity() const;
    void add (const Book &b);
    Book* find(const std::string &bookID) const;
    Catalog& operator= (Catalog c);
private:
    Book* books;
    int theCapacity;
    int theSize;
    void swap(Catalog &c);
};

#include "class.h"
#include <algorithm>
Catalog::Catalog(int maxCapacity)
{
    theCapacity = maxCapacity;
    theSize = 0;
    books = new Book[theCapacity];
}
Catalog::Catalog(const Catalog& c)
{
    theCapacity = c.theCapacity;
    books = new Book[theCapacity];
    for(int i = 0; i < c.theSize;; ++i)
        books[i] = c.books[i];
    theSize = c.theSize;
}
Catalog::~Catalog()
{
    delete[] books;
}
Catalog& Catalog::operator= (const Catalog &c)
{
    if (this != &c)
        Catalog(c).swap(*this);    
    return *this;
}
void Catalog::swap(Catalog &c)
{
    std::swap(books, c.books);
    std::swap(theSize, c.theSize);
    std::swap(theCapacity, c.theCapacity);
}
int Catalog::size() const
{
    return theSize;
}
int Catalog::capacity() const
{
    return theCapacity;
}
void Catalog::add (const Book &b)
{
    Book *book = find(b.getID());
    if (book) {
        *book = b;
    }
    else if (theSize < theCapacity)
    {
        int i;
        for (i = theSize; i && b < books[i-1]; --i) {
            books[i] = books[i - 1];
        }
        books[i] = b;
        ++theSize;
    }
    // Debugging only
    /*
    for (int i = 0; i < theSize; ++i) {
        cout << books[i] << endl;
    }
    */
}
Book* Catalog::find(const std::string &bookID) const
{
    for (int i = 0; i < theSize; ++i)
    {
        if (books[i].getID() == bookID)
            return &books[i];
    }
    return 0;
}

话虽如此,如果您使用 std::vector 和 STL 算法,这将更简单、更容易管理。 让STL为您完成艰苦的工作:

#include <vector>
class Catalog
{
public:
    Catalog (int initialCapacity = 100);
    int size() const;
    int capacity() const;
    void add (const Book &b);
    Book* find(const std::string &bookID) const;
private:
    std::vector<Book> books;
};

#include "class.h"
#include <algorithm>
Catalog::Catalog(int initialCapacity)
{
    books.reserve(initialCapacity);
}
int Catalog::size() const
{
    return books.size();
}
int Catalog::capacity() const
{
    return books.capacity();
}
void Catalog::add (const Book &b)
{
    Book *book = find(b.getID());
    if (book) {
        *book = b;
    }
    else {
        books.insert(std::upper_bound(books.begin(), books.end(), b), b);
    }
    // Debugging only
    /*
    for (Book &book: books) {
        cout << book << endl;
    }
    */
}
Book* Catalog::find(const std::string &bookID) const
{
    auto iter = std::find_if(books.begin(), books.end(), [&bookID](const Book &b){ return (b.getID() == bookID); });
    if (iter != books.end())
        return &*iter;
    return 0;
}