为结构动态分配内存 我正在使用C++类,并有一个任务,它需要我动态分配内存。我不记得曾经在课堂上讨论过这一点,在继续上课之前,我们只简单地讨论了新的操作符。现在我必须
动态分配学生,然后提示用户输入学生的名字、姓氏和-number(ID号) 我的结构是这样写的为结构动态分配内存 我正在使用C++类,并有一个任务,它需要我动态分配内存。我不记得曾经在课堂上讨论过这一点,在继续上课之前,我们只简单地讨论了新的操作符。现在我必须,c++,dynamic,struct,C++,Dynamic,Struct,动态分配学生,然后提示用户输入学生的名字、姓氏和-number(ID号) 我的结构是这样写的 struct Student { string firstName, lastName, aNumber; double GPA; }; 我试过Student student1=新学生但这不起作用,我不确定如何使用结构动态执行此操作。将定义更改为 struct Student { string firstName, lastName, aNumber; double
struct Student
{
string firstName, lastName, aNumber;
double GPA;
};
我试过
Student student1=新学生代码>但这不起作用,我不确定如何使用结构动态执行此操作。将定义更改为
struct Student
{
string firstName, lastName, aNumber;
double GPA;
};
注意,我已经更改了struct关键字的位置
你必须做Student*student1=新学生
当为结构动态分配内存时,会得到指向结构的指针
处理完学生后还必须记住通过执行删除学生1来释放动态分配的内存。您可以使用std::shared\u ptr自动管理动态分配的内存。struct
位于它定义的结构名称之前。:)
当您尝试新学员时,您看到的错误是什么?为什么它不工作?new返回指向对象的指针。。。所以你想要
struct Student* student1 = new Student;
new
语句返回指向new
ed实例的指针。因此,您需要将student1
定义为指针
struct Student * student1 = new Student;
这应该是您所需要的:
std::unique_ptr<Student> x(new Student);
std::unique_ptr x(新学生);
为什么要使用新的?只需声明变量的一个实例:
Student student1;
根据学生的定义
,它看起来没有身份,
而且它当然是可复制的,所以您可能永远都不应该new
it
(我还为它提供了一个构造函数,这样它就可以初始化了
从定义它的那一刻起就正确。)
动态分配学生,然后提示用户输入学生的名字、姓氏和-number(ID号)
此作业要求您拥有一个未完全初始化的Student
对象,直到您可以使用用户提供的信息对其进行更新。一般来说,这是一个非常糟糕的想法,因为仅仅有可能存在一个未完全初始化的对象(例如,在本例中缺少适当的id值),这使得使用该对象的代码更加复杂,因为它必须检查是否存在一个适当的id值。而正确使用的复杂性,再加上未能认识到正确使用需要复杂性,会吸引诸如mad–ungood之类的bug
<>这就是为什么C++扩展C在分配和初始化之间提供了非常强的耦合。用C++ <强> >代码>新< /COD> <强>表达式,既可以获得成功的分配,也可以获得成功的初始化,或者两者都不(它在失败时清除)。这就是问题应该更好地教导的
因此,我将教你接受可接受的C++实践(尽管使用<代码>新的< /代码>一般是要避免的),这意味着回答这个修改的问题:
提示用户输入学生的名字、姓氏和-number(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;
}
但是,除了作业要求使用动态分配外,具有上述功能的程序将在没有任何动态分配或智能指针的情况下编写。studentFromInput
函数只需按值返回一个Student
对象,即复制。这几乎是一个悖论,但现代C++的基础上非常繁琐,而且仍然产生相当快的程序!
当然,为了避免机器代码中实际发生复制,隐藏着大量肮脏的伎俩。如果你想理解语法的概念或想感受语法的感觉。。只需始终处理此struct student=new student
语法。
as struct student=新尺寸(学生);表示您只是简单地将数据类型放入sizeof()-fn中进行大小确认。并不是说将Student放在struct之前。但是学生*修复了它,我必须返回指针,所以谢谢:]我必须返回指向main的指针,并在程序结束时删除它。@sircrisp这正是unique\u ptr
所做的。除非它是为你做的。不要使用原始指针,它们很糟糕。听起来你真的需要查阅你的课堂材料。或者一个。您需要使用->
通过指针访问成员。@sircrisp:从这个问题来看,这不是您学习的方式。我对此表示怀疑。当你甚至不知道他为什么要使用new
时,你怎么能做出这样的声明呢?詹姆斯:因为几乎没有任何情况下,原始new
实际上是合理的,而不是立即构建你选择的智能指针?胡说八道。很大程度上取决于应用程序,但大多数指针应该是原始指针。(就此而言,您无法避免它,因为这是一个原始指针。)unique\u ptr
具有非常特定的语义;当您需要这些语义时,它是很好的,但当您不需要时,使用它是错误的。因为我们不知道他为什么动态分配(我怀疑事实上,他根本不应该使用动态分配),我们不能对unique\u ptr
@JamesKanze的适当性做出任何假设:我从来没有说过任何关于原始指针的一般性的事情。只有在一般情况下,动态分配的资源应该始终受到资源管理类(如智能指针)的保护。当然,他可能根本不需要动态分配,而是请求动态分配,而不需要提及
// 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;
}