我的大脑从来没有真正掌握链表和指针的细节,但我正在尝试用一些C ++任务来帮助朋友。 (在我再进一步之前,是的,有std :: list但我正在寻找一个学术答案,也许会让链接列表对他和我自己更容易理解。)
我们需要做的是根据用户输入生成对象的链接列表(Employee
对象),然后将该信息显示给用户。每当我尝试将对象分配到链接列表容器时,就会发生段错误。
我有以下链接列表对象:
class LinkedListContainer {
private:
Employee *emp;
LinkedListContainer *next;
public:
Employee getEmployee() { return *emp; }
void setEmployee(Employee *newEmp) {
*emp = *newEmp // This is what is causing the segfault
}
LinkedListContainer getNext() { return *next; }
void setNext(LinkedListContainer *newContainer) {
*next = *newContainer;
}
}
我确信我做的事情非常糟糕。
答案 0 :(得分:5)
查看您的班级,似乎没有指针emp
设置为指向实际对象的位置。
这一行:
*emp = *newEmp;
将newEmp
指向的对象的值分配给emp
指向的对象。除非两个指针都指向有效对象,否则代码将具有未定义的行为。
您最好将emp
作为Employee对象,而不是指向需要手动管理指向对象生命周期的对象的指针。
这假定您的LinkedListContainer
类是拥有Employee
的节点。
另一方面,当你这样做时:
*next = *newContainer;
从命名我会假设您只想将下一个指针指向您可能想要做的另一个LinkedListContainer
:
next = newContainer;
因为这会将指针的值赋给变量next
。
当你设计你的类并使用指针时,你需要清楚,哪些对象拥有哪些其他对象,并确保你适当地管理它们的生命周期。
答案 1 :(得分:2)
*emp = *newEmp;
应该是:
emp = newEmp;
这样你就可以指定指针,而不是指针指向的对象。
答案 2 :(得分:1)
您的emp
指针未初始化,因此当您尝试在*emp
中取消引用它(setEmployee()
)时,您尝试访问不属于您的内存(因此会出现段错误)
你可能最好按值保持Employee(假设它不是多态的)并通过const引用传递setEmployee一个Employee对象:
class LinkedListContainer {
Employee emp;
// ...
void setEmployee(const Employee& newEmp) {
emp = newEmp;
}
// ...
};
当然,您还需要调整其他成员函数,以反映使用值与指针的对比。
祝你好运!答案 3 :(得分:0)
*emp = *newEmp
你不想这样做 - 事实上,你根本不想取消引用任何指针。
emp = newEmp
答案 4 :(得分:0)
默认情况下,\ temp是指向无处的指针。通过写作
*emp = *newEmp;
您尝试将newEmp的内容分配给emp所指向的任何内存位置。如上所述,emp指向无处,所以你在这里取消引用一个NULL指针,这会导致分段错误。
如果你的容器要包含一个完整的Employee,你最好将emp声明为Employee类型(不是指向Employee的指针)。然后
emp = *newEmp;
会起作用,虽然我不太确定这是否只需要修复你的LinkedListContainer。
答案 5 :(得分:0)
您遇到的一个问题是由于访问指针时的前导*。 *告诉编译器在访问指针时,不是读取指针所指向的地址,而应该读取指针所指向的位置的值。
一个例子是变量就像拥有价值观的房屋。指针就像房子上的地址。通常,当编译器读取指针时,它只能看到地址。当你把指针放在*前面时它会告诉编译器查看“house”里面的值来提取其中的值。当您指定新地址时,您不想使用*,否则您正在复制值而不是地址。
所以你要做的事情就是在setNext中,例如:
next = newContainer;
答案 6 :(得分:0)
以前的答案解释了分段错误的原因。无论如何,如果您需要该样本供学术使用,那么恕我直言,您忘记了课堂成员的初始化。第二个问题是内存管理 - 谁分配/释放这些对象?在你的样本中也没有构造函数,也没有析构函数:)
你的课程可能如下所示:
class LinkedListContainer
{
public:
LinkedListContainer()
: d_emp( 0 )
, d_next( 0 )
{
}
bool isValid() const
{
const bool result = ( d_emp != 0 );
return result;
}
const Employee& getEmployee() const
{
assert( isValid() );
return *d_emp;
}
void setEmployee( Employee* emp )
{
d_emp = emp;
}
LinkedListContainer* getNext()
{
return d_next;
}
void setNext( LinkedListContainer* next )
{
d_next = next;
}
private:
Employee* d_emp;
LinkedListContainer* d_next;
};
如果您不想打扰Employee对象的内存管理,那么只需使用boost库中的shared_ptr。
typedef boost::shared_ptr< Employee > SmartEmployee;
class LinkedListContainer
{
public:
LinkedListContainer()
: d_next( 0 )
{
}
bool isValid() const
{
return d_emp;
}
const Employee& getEmployee() const
{
assert( isValid() );
return *d_emp;
}
void setEmployee( SmartEmployee emp )
{
d_emp = emp;
}
LinkedListContainer* getNext()
{
return d_next;
}
void setNext( LinkedListContainer* next )
{
d_next = next;
}
private:
SmartEmployee d_emp;
LinkedListContainer* d_next;
};