我有一个名为object
的简单类,我遇到了问题。如果我调用它,会导致段错误的一种方法。我不明白为什么。
typedef class object
{
private:
short id;
std::string name;
SDL_Rect offset;
public:
object();
object(short i, std::string n);
~object();
object(const object &o);
object& operator = (const object &o);
std::string get_name();
void set_name(std::string n);
} object;
object::object()
{
id = 0;
name = "";
offset.x = 0;
offset.y = 0;
offset.w = 0;
offset.h = 0;
}
object::object(short i, std::string n)
{
id = i;
name = n;
offset.x = 0;
offset.y = 0;
offset.w = 0;
offset.h = 0;
}
object::~object()
{
delete &offset;
delete &id;
delete &name;
}
object& object::operator=(const object &o)
{
if(this != &o)
{
delete &name;
name.assign(o.name);
delete &id;
id = o.id;
delete &offset;
offset = o.offset;
}
return *this;
}
object::object(const object &o)
{
id = o.id;
name = o.name;
offset = o.offset;
}
// Functions
std::string object::get_name()
{
return name;
}
void object::set_name(std::string n)
{
name = n;
}
我的main.cpp
int main( int argc, char** argv )
{
struct object *a = new object(0, "test");
struct object *b = new object(1, "another test");
printf(a->get_name().c_str());
printf("\n");
printf(b->get_name().c_str());
b = a;
printf("\n");
printf(b->get_name().c_str());
a->set_name("Another test");
printf("\n");
printf(a->get_name().c_str());
delete a;
printf("\nDeleted a");
delete b;
printf("\nDeleted b");
return 0;
}
如果我拨打a->set_name("Another test");
,我会收到段错误。如果我省去电话,没有问题,一切正常。我可能错过了一些简单的东西,但我找不到它。它不会在赋值时出现段错误,但如果该行存在则在删除指针时崩溃。
答案 0 :(得分:4)
由于构造函数中没有new
任何内容,因此析构函数中delete
的任何内容都是错误的。只需将析构函数留空,或者甚至更好,完全摆脱它。编译器生成的析构函数完全符合您的要求(没有)。您也不必手动编写复制构造函数和复制赋值运算符,只需将它们丢弃即可。
也不需要动态创建对象,使用本机C ++输入/输出工具打印字符串要容易得多。你可以摆脱使用默认参数重载构造函数。通过reference-to-const传递和返回字符串比按值传递它们更有效。最后但同样重要的是,让我们保持正确。这是我对你的代码的清理:
#include <iostream>
class object
{
short id;
std::string name;
SDL_Rect offset;
public:
object(short i = 0, const std::string& n = "");
const std::string& get_name() const;
void set_name(const std::string& n);
};
object::object(short i, const std::string& n) : id(i), name(n)
{
offset.x = 0;
offset.y = 0;
offset.w = 0;
offset.h = 0;
}
const std::string& object::get_name() const
{
return name;
}
void object::set_name(const std::string& n)
{
name = n;
}
int main(int argc, char** argv)
{
object a(0, "test");
object b(1, "another test");
std::cout << a.get_name() << "\n";
std::cout << b.get_name() << "\n";
b = a;
std::cout << b.get_name() << "\n";
a.set_name("Another test");
std::cout << a.get_name() << "\n";
}
答案 1 :(得分:3)
delete &name;
您只能通过调用delete
获得new
个指针。 name
是该类的成员变量;你不能删除它,也不会删除它。当类被销毁时,它也会破坏任何成员变量。
只有你有成员指针(如果你有std::string* name
),你必须确保正确地清理它们,但即便如此,你也应该更喜欢使用智能指针,如{{1 }},scoped_ptr
或shared_ptr
(如果您的实现支持它)。
答案 2 :(得分:0)
name
是string
并管理自己的内存。您在结构中的声明是正确的,您可以assign
在已经存在的任何值之上。当结构超出范围时,无需做任何事情。
请注意,get_name方法返回一个新副本,因为它按值返回。您可以改为返回对结构中的内容的引用,只要在拥有的结构超出范围后不使用返回的值:
const string& get_name() { return name; }
您应该按如下方式更改setter声明,因为传递副本没有任何好处(过多的值传递是新C ++开发人员的常见错误)。
void set_name(const string& newValue)