2017-05-25 43 views
-1

试图熟悉“3规则”,并且无法让复制构造函数工作。其中一个类私有成员返回0时,它应该有一个值3.动态分配数组的复制构造函数

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

class.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; 
}; 

class.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; 
} 

c1return c在另一个函数的结果,当我打电话c1.size()的main.cpp后来,通过使用的调试器来自复制构造函数,然后进入析构函数。但c1.size()返回为0,虽然复制构造函数theSize = c.size()的值为3时,通过。

book.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; 
} 

main.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; 
    } 
} 
+2

'*书籍= *(c.books);'将一个元素,而不是整个数组 – user4581301

+0

复制@ user4581301所以也许'for'循环来复制?还是有更好的方法来复制数组? –

+1

For循环或['std :: copy'](http://en.cppreference.com/w/cpp/algorithm/copy)。 – user4581301

回答

1

尝试一些更喜欢这个:

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; 
} 
1

关注规则:使用std::vector<Book>来代替数组指针和大小。

您的容量是大小上的限制。

当在能力。使用相等的范围来找到插入的位置,替换最后一个元素然后std旋转。

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

+0

绝对是广义上的正确答案,但是OP有一个明确的目标,就是搞清楚三条规则。 – user4581301

+0

@Yakk宁愿坚持三条规则,因为它更适用于我在不久的将来所做的事情。 –

+0

@pasta然后写*只*管理资源的东西。两者都是在脚下射击自己。 – Yakk