sir*_*isp 9 c++ struct dynamic
我正在学习一个C++类并且有一个赋值,它要求我为一个struct动态分配内存.我不记得曾经在课堂上讨论这个问题,我们在上课new
之前只是简单地谈过了 算子.现在我必须
"动态分配学生,然后提示用户输入学生的名字,姓氏和A号码(身份证号码)."
我的结构写得像
struct Student
{
string firstName, lastName, aNumber;
double GPA;
};
Run Code Online (Sandbox Code Playgroud)
我尝试Student student1 = new Student;
但是这不起作用,我不确定我是如何用结构动态地做这个的.
par*_*mar 15
将您的定义更改为
struct Student
{
string firstName, lastName, aNumber;
double GPA;
};
Run Code Online (Sandbox Code Playgroud)
注意我已经更改了struct关键字的位置
而你必须做Student* student1 = new Student
.
当您为结构动态分配内存时,您将获得指向结构的指针.
完成学生后,您还必须记住通过执行a释放动态分配的内存delete student1
.您可以使用std :: shared_ptr自动管理动态分配的内存.
这应该是你需要的:
std::unique_ptr<Student> x(new Student);
Run Code Online (Sandbox Code Playgroud)
"动态分配学生,然后提示用户输入学生的名字,姓氏和A号码(身份证号码)."
此分配要求您拥有一个未完全初始化的Student
对象,直到您可以使用用户提供的信息更新它.一般来说这是一个非常糟糕的想法,因为仅具有未完全初始化对象的可能性(例如,在这种情况下缺少正确的id值)使得使用该对象的代码更复杂,因为它必须检查例如是否存在是一个正确的id值.正确使用的复杂性,以及未能认识到正确使用所需的复杂性,吸引了疯狂的错误.
这就是扩展C的C++ 在分配和初始化之间提供了非常强大的耦合的原因.使用C++ new
表达式,您既可以获得成功的分配,也可以获得成功的完整初始化,或者两者都没有(它会在失败时清除).这就是问题应该更好的教导!
因此,除了上面引用的给定问题,我将教你可接受的C++实践(尽管new
通常要避免使用),这意味着回答这个修改过的问题:
提示用户输入学生的名字,姓氏和A号码(ID号),然后
Student
使用这些值动态分配对象.
好的,这里是:
// The Dynamic Student, version 1.
// "Prompt the user for student’s first name, a last name, and A - number
// (ID), and then dynamically allocate a `Student` object with these values."
#include <assert.h> // assert
#include <iostream> // std::cout,std::endl
#include <string> // std::string
#include <sstream> // std::istringstream
#include <stdexcept> // std::exception, std::runtime_error
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
#define CPP_NO_COPYING_OF( Clazz ) \
Clazz( Clazz const& ); \
Clazz& operator=( Clazz const& )
namespace cpp {
using namespace std;
bool hopefully( bool const c ) { return c; }
bool throwX( string const& s ) { throw runtime_error( s ); }
string lineFromInput()
{
string result;
getline( cin, result )
|| throwX( "lineFromInput: std::getline failed (EOF?)" );
return result;
}
string lineFromInput( string const& prompt )
{
cout << prompt;
return lineFromInput();
}
int intFromInput( string const& prompt )
{
istringstream stream( lineFromInput( prompt ) );
int result;
stream >> result
|| throwX( "intFromInput: input line was not a valid number spec" );
return result;
}
} // namespace cpp
namespace blah {
using namespace std;
using namespace cpp;
struct Student
{
CPP_NO_COPYING_OF( Student );
int const id;
string const firstName;
string const lastName;
Student(
int const _id,
string const _firstName,
string const _lastName
)
: id( _id ), firstName( _firstName ), lastName( _lastName )
{}
};
Student* studentFromInput()
{
cout << "It's -- the Dynamic Student program!" << endl;
string const firstName = lineFromInput( "First name, please? " );
hopefully( firstName != "" )
|| throwX( "Sorry, the first name can't be nothing." );
string const lastName = lineFromInput( "Last name, please? " );
hopefully( lastName != "" )
|| throwX( "Sorry, the last name can't be nothing." );
int const id = intFromInput( "And the student id is...? " );
hopefully( id > 0 )
|| throwX( "Sorry, the id can't be negative or zero." );
return new Student( id, firstName, lastName );
}
} // namespace blah
void cppMain()
{
using namespace blah;
Student const* const pStudent = studentFromInput();
try
{
// Use the student object, e.g.
cout
<< "The student is "
<< pStudent->firstName << " " << pStudent->lastName
<< ", with id " << pStudent->id << "."
<< endl;
// Then:
delete pStudent;
}
catch( std::exception const& )
{
delete pStudent;
throw; // Rethrows the exception.
}
}
int main()
{
using namespace std;
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
Run Code Online (Sandbox Code Playgroud)
对于每个执行的new
表达式(执行分配和初始化),理想情况下应该是delete
表达式的相应执行,它清理并释放内存块以便可以重用它.delete
理想情况下,即使某些内容失败也会执行该表达式并抛出异常.因此try
和catch
.
但是,像这样编码是容易出错和冗长的.
相反,在更惯用的C++编程一个将使用一个智能指针,保存一个指针,并提供指针操作(所以它看起来像一个对象是一个指针),其析构函数自动执行一个delete
当指针不再使用的表达.C++标准库有几个这样的智能指针类.作为一般规则,使用最严格的智能指针,因为它具有最小的开销,并且很可能支持转换为更一般的智能指针,而相反的可能性则小得多,不太可能.
所以在这种情况下,您可以使用例如C++ 11 std::unique_ptr
或者如果您的编译器是旧的,C++ 03 std::auto_ptr
,来自<memory>
标题:
// The Dynamic Student, version 2 -- using smart pointer.
// "Prompt the user for student’s first name, a last name, and A - number
// (ID), and then dynamically allocate a `Student` object with these values."
#include <assert.h> // assert
#include <iostream> // std::cout,std::endl
#include <memory> // std::unique_ptr
#include <string> // std::string
#include <sstream> // std::istringstream
#include <stdexcept> // std::exception, std::runtime_error
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
#define CPP_NO_COPYING_OF( Clazz ) \
Clazz( Clazz const& ); \
Clazz& operator=( Clazz const& )
namespace cpp {
using namespace std;
bool hopefully( bool const c ) { return c; }
bool throwX( string const& s ) { throw runtime_error( s ); }
string lineFromInput()
{
string result;
getline( cin, result )
|| throwX( "lineFromInput: std::getline failed (EOF?)" );
return result;
}
string lineFromInput( string const& prompt )
{
cout << prompt;
return lineFromInput();
}
int intFromInput( string const& prompt )
{
istringstream stream( lineFromInput( prompt ) );
int result;
stream >> result
|| throwX( "intFromInput: input line was not a valid number spec" );
return result;
}
} // namespace cpp
namespace blah {
using namespace std;
using namespace cpp;
struct Student
{
CPP_NO_COPYING_OF( Student );
int const id;
string const firstName;
string const lastName;
Student(
int const _id,
string const _firstName,
string const _lastName
)
: id( _id ), firstName( _firstName ), lastName( _lastName )
{}
};
unique_ptr<Student> studentFromInput()
{
cout << "It's -- the Dynamic Student program!" << endl;
string const firstName = lineFromInput( "First name, please? " );
hopefully( firstName != "" )
|| throwX( "Sorry, the first name can't be nothing." );
string const lastName = lineFromInput( "Last name, please? " );
hopefully( lastName != "" )
|| throwX( "Sorry, the last name can't be nothing." );
int const id = intFromInput( "And the student id is...? " );
hopefully( id > 0 )
|| throwX( "Sorry, the id can't be negative or zero." );
return unique_ptr<Student>( new Student( id, firstName, lastName ) );
}
} // namespace blah
void cppMain()
{
using namespace blah;
unique_ptr<Student> const pStudent = studentFromInput();
// Use the student object, e.g.
cout
<< "The student is "
<< pStudent->firstName << " " << pStudent->lastName
<< ", with id " << pStudent->id << "."
<< endl;
}
int main()
{
using namespace std;
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
Run Code Online (Sandbox Code Playgroud)
但是,除了赋值使用动态分配的要求外,具有上述功能的程序将在没有任何动态分配或智能指针的情况下编写.该studentFromInput
函数只是Student
按值返回一个对象,复制.这几乎是一个悖论,但现代C++非常依赖于复制,并且仍然可以生成相当快的程序!
当然,在引擎盖下有大量的肮脏技巧,以避免复制实际发生在机器代码中.
归档时间: |
|
查看次数: |
53468 次 |
最近记录: |