c++类指针删除段错误

发布于 2024-09-28 22:53:38 字数 1903 浏览 2 评论 0原文

我有一个名为 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");,我会遇到段错误。如果我不打电话,就没有问题,一切正常。我可能错过了一些简单的东西,但我找不到它。它不会在分配时出现段错误,但如果该行在那里,则在删除指针时会崩溃。

I've got a simple class called object that I'm having a problem with. Theres one method which causes a segfault if I call it. I don't understand why.

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;
}

And my 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;
}

If I call a->set_name("Another test");, I get a segfault. If I leave out the call, no problems, everything works. I'm probably missing something simple, but I can't find it. It doesn't segfault on the assignment, but if that line is there it crashes when deleting the pointer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

宫墨修音 2024-10-05 22:53:38

由于您没有在构造函数中new任何内容,因此在析构函数中delete任何内容都是错误的。只需将析构函数留空即可,或者更好的是,完全摆脱它。编译器生成的析构函数完全按照您的要求执行(什么都不执行)。您也不必手动编写复制构造函数和复制赋值运算符,只需将它们扔掉即可。

也不需要动态创建对象,并且使用本机 C++ 输入/输出工具打印字符串要容易得多。并且您可以摆脱使用默认参数重载构造函数的情况。通过引用 const 来传递和返回字符串比通过值传递字符串更有效。最后但并非最不重要的一点是,让我们保持 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";
}

Since you didn't new anything in the constructor, it is wrong to delete anything in the destructor. Just leave the destructor empty, or even better yet, get rid of it completely. The compiler-generated destructor does exactly what you want (nothing). You also don't have to write the copy constructor and the copy assignment operator by hand, just throw them away.

There is also no need to create the objects dynamically, and printing strings is a lot easier with the native C++ input/output facilities. And you can get rid of overloading the constructor with default arguments. And passing and returning strings by reference-to-const is more efficient than passing them by value. Last but not least, let's be const correct. Here is my cleanup of your code:

#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";
}
-黛色若梦 2024-10-05 22:53:38
delete &name;

您只能删除通过调用new获得的指针。 name是类的成员变量;您无法删除它,也永远不需要删除它。当类被销毁时,它也会销毁所有成员变量。

仅当您的成员是指针时(例如,如果您有 std::string* name),您就必须确保正确清理它们,但即便如此,您也应该更喜欢使用 smart诸如 scoped_ptrshared_ptrunique_ptr 之类的指针(如果您的实现支持的话)。

delete &name;

You can only delete pointers that you obtained by calling new. name is a member variable of the class; you can't delete it, nor will you ever have to. When the class is destroyed, it will destroy any member variables as well.

It's only if you have members that are pointers (like if you had std::string* name) that you would have to be sure to properly clean them up, but even then you should prefer to use smart pointers like scoped_ptr, shared_ptr, or unique_ptr (if your implementation supports it).

舂唻埖巳落 2024-10-05 22:53:38

name 是一个string 并管理自己的内存。您在结构中的声明是正确的,您可以在已经存在的任何值之上分配。当结构超出范围时也无需执行任何操作。

请注意,您的 get_name 方法返回一个新副本,因为它按值返回。您可以像这样返回对结构中内容的引用,前提是在所属结构超出范围后不使用返回值:

const string& get_name() { return name; }

您应该按如下方式更改 setter 声明,因为传递副本没有任何好处(过多传递按值是新 C++ 开发人员中的常见错误)。

void set_name(const string& newValue)

name is a string and manages its own memory. Your declaration in the struct is correct, you can just assign on top of any value that's already there. No need to do anything when the struct goes out of scope either.

Note that your get_name method returns a new copy since it returns by value. You could instead return a reference to what's in the struct like this, provided the returned value is not used after the owning struct goes out of scope:

const string& get_name() { return name; }

You should change the setter declaration as follows, since there's no benefit in passing a copy (excessive pass by value is a common error among new C++ developers).

void set_name(const string& newValue)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文