动态分配的对象未初始化
Dynamic allocated object not initializing
我正在尝试为学校的家庭作业准备一个图书馆管理系统。我编写了代码,但在bool Library::add_book(const Book&)
函数中,我无法将 book 初始化为动态数组。我重载了= operator
来初始化Book
类,当我在 main 中声明一个Book
对象时,它可以工作。但是对于动态分配的数组,它不起作用。
#include <iostream>
class Author{
public:
std::string name;
Author(){}
Author(const std::string& name){
this -> name = name;
}
};
class Book{
private:
std::string _title, _isbn;
int _edition;
Author *_author = new Author;
public:
Book(){
*_author = Author("NULL");
_isbn = "INVALID";
}
Book(const std::string& title,
const std::string& isbn,
const std::string& author,
int edition){
_title = title;
_isbn = isbn;
_edition = edition;
*_author = Author(author);
}
bool query_isbn(const std::string&);
Book& operator=(const Book&);
friend std::ostream &operator <<(std::ostream &, Book&);
};
class Library{
private:
Book *_book = nullptr;
int *_numberOfBorrows = nullptr;
int _numberOfBook, _maxNumberBook;
public:
Library(int maxNumberBook){
_maxNumberBook = maxNumberBook;
_book = new Book[_maxNumberBook];
_numberOfBorrows = new int[_maxNumberBook];
for(int i = 0; i < _maxNumberBook; i++){
_book[i] = Book();
_numberOfBorrows[i] = 0;
}
}
~Library(){
delete []_book;
_book = NULL;
delete []_numberOfBorrows;
_numberOfBorrows = NULL;
}
bool add_book(const Book&);
void operator+= (const Book&);
const Book& borrow_book(const std::string&);
friend std::ostream& operator <<(std::ostream&, Library&);
};
bool Book::query_isbn(const std::string& isbn){
if(_isbn == isbn)
return true;
else
return false;
}
Book& Book::operator=(const Book& book){
Book ret;
ret._author -> name = book._author -> name;
ret._edition = book._edition;
ret._isbn = book._isbn;
ret._title = book._title;
return ret;
}
std::ostream &operator << (std::ostream& output, Book& obj){
output << obj._author -> name << ", " << obj._title << ", " << obj._isbn << std::endl;
return output;
}
bool Library::add_book(const Book& book){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn("INVALID")){
_book[i] = book;
_numberOfBook++;
return true;
}
}
return false;
}
void Library::operator+= (const Book& book){
add_book(book);
}
const Book& Library::borrow_book(const std::string& isbn){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn(isbn)){
_numberOfBorrows[i] = _numberOfBorrows[i] + 1;
return _book[i];
}
}
std::cout << "ISBN with " << isbn << " does not exist" << std::endl;
}
std::ostream& operator <<(std::ostream& output, Library& lib){
for(int i = 0; i < lib._maxNumberBook; i++){
output << lib._book[i];
output << "Borrowed: " << lib._numberOfBorrows[i] << std::endl;
for(int i = 0; i < 38; i++)
output << '=';
std::cout << std::endl;
}
return output;
}
int main(int argc, char** argv){
Library lib(3);
Book obj1("The 8051 Microcontroller & Embedded Systems", "1234-456789123", "Mazidi", 1),
obj2("Fundamentals of Database Systems", "7899-456456123", "Elmasri", 2),
obj3("Electric Circuits", "1478-258963258", "Nilsson", 3);
lib.add_book(obj1);
lib.add_book(obj2);
lib.add_book(obj3);
lib.borrow_book("6584-258963258");
lib.borrow_book("1234-456789123");
lib.borrow_book("7899-456456123");
lib.borrow_book("1478-258963258");
std::cout << lib;
return 0;
}
我希望它输出书籍属性,但它输出与下面相同...
ISBN with 6584-258963258 does not exist
ISBN with 1234-456789123 does not exist
ISBN with 7899-456456123 does not exist
ISBN with 1478-258963258 does not exist
NULL, , INVALID
Borrowed: 0
======================================
NULL, , INVALID
Borrowed: 0
======================================
NULL, , INVALID
Borrowed: 0
======================================
互相玩有几个错误。我将只介绍与所问问题直接相关的两个问题。
问题1:
bool Library::add_book(const Book& book){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn("INVALID")){
_book[i] = book;
_numberOfBook++;
return true;
}
}
return false;
}
利用
Book& Book::operator=(const Book& book){
Book ret;
ret._author -> name = book._author -> name;
ret._edition = book._edition;
ret._isbn = book._isbn;
ret._title = book._title;
return ret;
}
这不会分配给给定的Book
.它不是分配给*this
,而是创建一个新的Book
并分配给它。因此,作业不执行任何操作。
旁注:由于Book ret;
是局部变量,因此无法安全地返回对它的引用。它在函数末尾超出范围,调用方左侧持有无效引用。编译器可能会警告您这一点。
operator=
应该看起来像
Book& Book::operator=(const Book& book){
*_author = *book._author;
_edition = book._edition;
_isbn = book._isbn;
_title = book._title;
return *this;
}
但这根本不是必要的。
使用自定义operator=
的原因大概是为了处理_author
成员,即指针。这是使用自有指针的糟糕地方。Book
不应拥有Author
的所有权,以便许多书籍可以共享相同的Author
,或者应自动分配_author
,以便许多Book
可以拥有相同Author
的副本。目前使用的是复制方法,但有一个指向动态分配Author
的指针。此处不适合使用动态分配进行复制。
使用自动变量或非拥有指针(或std::shared_ptr
(进行复制消除了对自定义operator=
的需要,消除了这个问题。请参阅零法则了解更多信息。你选择哪条路是你必须做出的决定。
问题2
const Book& Library::borrow_book(const std::string& isbn){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn(isbn)){
_numberOfBorrows[i] = _numberOfBorrows[i] + 1;
return _book[i];
}
}
std::cout << "ISBN with " << isbn << " does not exist" << std::endl;
}
在所有情况下都不返回Book &
。如果找不到这本书,borrow_book
的来电者不会得到任何回复,他们会得到一些完全不确定的东西。现代编译器也会标记此错误。
这里有几个常见的解决方案。返回std::optional
或std::pair<bool, const Book*>
都提供了可以测试有效结果的内容。返回const Book *
允许返回nullptr
,再次可以测试有效Book
。该函数还可以返回bool
并更新参数。
这可能是我在 C 语言中的成长经历,但我认为在这里返回一个原始的、无主的指针是最合适的,但这是意见。
const Book * Library::borrow_book(const std::string& isbn){
for(int i = 0; i < _maxNumberBook; i++){
if(_book[i].query_isbn(isbn)){
_numberOfBorrows[i]++;
return &_book[i];
}
}
std::cout << "ISBN with " << isbn << " does not exist" << std::endl;
return nullptr;
}
旁注:由于_maxNumberBook
与图书馆中实际存储的书籍数量没有任何联系,因此for(int i = 0; i < _maxNumberBook; i++){
风险很高。_book[i]
可能尚未设置为定义的值。
- C++使用整数的压缩数组初始化对象
- 如何使用cudaMallocManaged在指针位置初始化对象?(C++)
- 在 c++ 中初始化对象
- C++ 手动分配和初始化对象
- 使用运算符"="在C++中用值初始化对象
- 当我不需要数据库中的所有值时,如何部分初始化 c++ 对象?
- 如何初始化对象数组?
- 在C++中使用默认构造函数初始化对象的不同方法
- 使用默认构造函数初始化对象的不同方法
- 是否可以在编译时初始化对象的 C 样式函数指针,以便它调用对象的成员函数?
- 如何在线程中初始化对象,然后在其他地方使用它?
- 在没有默认构造函数时使用垃圾数据初始化对象
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- 初始化对象以在 C++08 中作为参数传递的首选语法是什么?
- 在 c++ 中复制对未初始化对象的引用
- 在成员变量在另一个文件中发生更改后,调用与初始化对象分开的函数
- 在不放置新运算符的情况下,在预分配的内存上使用虚函数初始化对象 - 这可能吗?如果没有,为什么
- 复制 CTOR 与赋值运算符以初始化对象(性能)
- 当您通过分配初始化C 对象时会发生什么
- 获取未初始化对象成员的地址是否定义良好?