问题描述
这是给“家庭作业”的,但这不是算法问题,而是编程问题。作为我的数据结构类项目的一部分,我必须编写一个类来充当数据库。那部分就完成了。我不是在询问算法,而是试图找出我认为明显愚蠢的错误。
PeopleDB 有两个构造函数,一个是默认构造函数,另一个是将输入文件作为参数并将其读入数据库以对其进行初始化。
这是代码片段,问题描述如下:
#include "People.h" // People class deFinition
#include "PeopleDB.h" // People database class
#include "PrecondViolatedExcep.h"
using namespace std;
int main(int argc,char *argv[])
{
// Define variables
string infilename;
PeopleDB mydb;
// Get the filename of the text file to process
infilename = argv[1];
// Try to open import the data into a database instance
try
{
cout << "Attempting to import DB entries from "<< infilename << endl;
PeopleDB mydb(infilename);
cout << "# A total of "<< mydb.countEntries() << " DB entries loaded." << endl;
}
catch(PrecondViolatedExcep e)
{
cout << e.what() << endl;
cout << "Exiting program.";
exit(1);
}
// display database contents
cout << endl;
cout << "# A total of "<< mydb.countEntries() << " DB entries found before display." << endl;
return 0;
} // end main
问题是,如果我不在 main() 循环的顶部包含 PeopleDB mydb; 构造函数,编译器就会说它无法识别 mydb.countEntries () 在主循环的倒数第二行。但是如果我确实包含它,很明显 try 循环中的 mydb 不会存活,因为程序的输出是:
Attempting to import DB entries from testinput.txt
# A total of 7 DB entries loaded.
# A total of 0 DB entries loaded.
我不想使用相同的变量 (mydb) 两次(我实际上认为这会在编译期间出错),但出于某种原因创建了 mydb在 try 块内的 PeopleDB 实例似乎无法在块外存活。我确信这对我来说是愚蠢的,但我没有看到它。这是漫长的一天,所以任何建议将不胜感激。
解决方法
您正在创建两个 myDb
类型的对象 PeopleDB
:一个在 main 的开头,另一个在 try
块中。后一个加载数据,但在 try 块的范围结束时被破坏。
正在打印的第二个是在主块中创建的那个,并且那个从未加载过数据。
有多种方法可以解决这个问题,例如提供一种方法来加载数据并在 try
块内调用它。另一种选择是在 try
块结束之前复制/移动/交换“内部”块与“外部”块(但在这种情况下我会提供不同的名称)。您的调用,但最重要的是:此时您有两个不同的对象:一个是加载数据,另一个是从中打印数据(结果为空)。
您声明了两个独立的 mydb
对象。
要么执行 try-catch 块中的所有操作,要么移动连接到另一个函数。
PeopleDB connect(const std::string& infilename) {
try
{
cout << "Attempting to import DB entries from "<< infilename << endl;
PeopleDB mydb(infilename);
cout << "# A total of "<< mydb.countEntries() << " DB entries loaded." << endl;
return mydb;
}
catch(PrecondViolatedExcep e)
{
cout << e.what() << endl;
cout << "Exiting program.";
exit(1);
}
return PeopleDB{};
}
int main(int argc,char *argv[])
{
// Get the filename of the text file to process
string infilename = argv[1];
PeopleDB mydb = connect(infilename);
// Display database contents
cout << endl;
cout << "# A total of "<< mydb.countEntries() << " DB entries found before display." << endl;
return 0;
} // end main
,
尝试在 try 块内使用移动赋值:
mydb = std::move(PeopleDB(infilename));
我之所以这么建议,是因为它避免在 try 块内创建新对象,因为在 try 块的作用域结束后,该对象将消失。
使用 move
的原因是为了防止创建对象两次:
- 使用构造函数调用一次
- 另一个使用复制构造函数调用
但是,现在我意识到 std::move
是多余的,因为 PeopleDB(infilename)
已经是一个右值引用,并且编译器将足够聪明以自行完成移动。
所以我的新建议是:
mydb = PeopleDB(infilename);