Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 虚拟类中如何利用字符串指针避免内存泄漏_C++_Class_Pointers_Overloading - Fatal编程技术网

C++ 虚拟类中如何利用字符串指针避免内存泄漏

C++ 虚拟类中如何利用字符串指针避免内存泄漏,c++,class,pointers,overloading,C++,Class,Pointers,Overloading,我正在编写一个基类,其中包含一个指向字符串的指针,现在我正在尝试使用赋值运算符编写一个派生类,用新值替换它。对于这个特定的项目,我需要将字符串存储为指针 起初,我尝试使用new,但编译失败 kolo& operator=(const kolo& ref){ if(this!=&ref){ delete kolor; kolor=new string(ref.kolor); r=ref.r; } return *this; } 我已将其

我正在编写一个基类,其中包含一个指向字符串的指针,现在我正在尝试使用赋值运算符编写一个派生类,用新值替换它。对于这个特定的项目,我需要将字符串存储为指针

起初,我尝试使用
new
,但编译失败

kolo& operator=(const kolo& ref){
  if(this!=&ref){
    delete kolor;
    kolor=new string(ref.kolor);
    r=ref.r;
  }
  return *this;
}
我已将其更改为使用赋值运算符,该运算符已成功编译。然而,valgrind现在报告内存泄漏以及其他问题

kolo& operator=(const kolo& ref){
  if(this!=&ref){
    delete kolor;
    *kolor=*ref.kolor;
    r=ref.r;
  }
  return *this;
}
为什么valgrind报告我的赋值运算符内存泄漏?

我的完整代码(波兰语):

class-figura{
受保护的:
字符串*kolor;
公众:
figura():kolor(新字符串(“nic”){}
图A(常量字符串和a1):kolor(新字符串(a1)){}
虚拟双极()常数=0;
虚空wypisz(ostream&out)常数{

out去掉指针,这样就有了规则0:)

class-figura
{
受保护的:
科洛尔线;
公众:
图a():kolor(“nic”){}
/*显式*/figura(常量字符串&s):kolor(s){
virtual~figura()=默认值;
虚拟双极()常数=0;
virtualvoid wypisz(ostream&out)const{out表示,如果您实现析构函数、复制赋值或复制构造函数中的任何一个,您需要实现这三个。您已经为
kolo
完成了此操作,但没有为
图a

在代码中的某个地方,
kolo
正在被复制构造(例如,在向量内部),并使用默认版本的
figurea
s copy constructor。这将简单地复制指针。现在,原始字符串已丢失,导致泄漏。新字符串由两个不同的对象指向,因此将被销毁两次。第二次销毁是导致无效读取和删除的原因

有多种方法可以实现复制赋值和复制构造函数,而不必重复代码

我还希望,因为
figurea
实际上是一个上面有
kolor
的类,所以
figurea
的复制分配应该负责,而不是
kolor
的复制分配。这样,如果您从
figurea
派生另一个类,您就不需要重新实现
kolor
复制


听起来你需要使用原始指针,但一般来说,写内存管理的最好方法是不要写内存管理。直接使用字符串,以及字符串的内置内存管理,会让事情变得更简单。或者,使用智能指针,比如
shared\ptr
可以让你完成cop自动删除和自动删除。< /P> <代码>新的字符串< /代码>?是否真的需要字符串指针而不是“代码> STD::String < /Cord>”?是否考虑异常安全?包含错误的问题?您将进入函数的第一个版本。但是,我怀疑问题在于,您在尝试复制它时没有取消引用
ref.kolor
新字符串(*ref.kolor);
。第二个版本会导致未定义的行为,因为您访问已删除的指针。@Spectra在运算符的第一个实现中,您应该使用kolor=new string(*ref.kolor);@vladFrommosco仍然在Valgrindt中泄漏内存。非常感谢您,这在类figura中起作用(我添加了复制构造函数)!
class figura {
  protected:
    string *kolor;
  public:
      figura() : kolor(new string("nic")) {}

      figura(const string& a1) : kolor(new string(a1)) {}

      virtual double pole() const = 0;

      virtual void wypisz(ostream& out) const {
        out<<*kolor;
      }

      friend ostream& operator<<(ostream& out,const figura& r);

      virtual ~figura() { delete kolor; }
    };

class kolo: public figura {
  protected:
    unsigned r;

  public:
    kolo(): figura(), r(0) {}

    kolo(const string& a1, const unsigned a2)  :figura(a1), r(a2) {}

    kolo(const kolo& ref) : figura(ref), r(ref.r) {}

    kolo& operator=(const kolo& ref) {
      if(this!=&ref) {
        delete kolor;
        *kolor=*ref.kolor;
        r=ref.r;
      }
      return *this;
    }

    double pole()const{
      return 3.14*r*r;
    }

    void wypisz(ostream& out)const{
      out<<"Kolor: "<<*kolor<<" "<<"Skladowe: "<<r<<endl;
    }

    friend ostream& operator<<(ostream& out,const kolo& r);
};
==1774== Invalid read of size 8
==1774==    at 0x49ABE34: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1774==    by 0x10AB7F: figura::~figura() (test.cpp:14)
==1774==    by 0x10B155: kolo::~kolo() (test.cpp:20)
==1774==    by 0x10A7B4: main (test.cpp:84)
==1774==  Address 0x4dc1c80 is 0 bytes inside a block of size 32 free'd
==1774==    at 0x483C1CF: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1774==    by 0x10AB8C: figura::~figura() (test.cpp:14)
==1774==    by 0x10B155: kolo::~kolo() (test.cpp:20)
==1774==    by 0x10B175: kolo::~kolo() (test.cpp:20)
==1774==    by 0x10A78B: main (test.cpp:102)
==1774==  Block was alloc'd at
==1774==    at 0x483AE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1774==    by 0x10AAD8: figura::figura(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (test.cpp:8)
==1774==    by 0x10AC27: kolo::kolo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) (test.cpp:25)
==1774==    by 0x10A467: main (test.cpp:84)
==1774== 
==1774== Invalid free() / delete / delete[] / realloc()
==1774==    at 0x483C1CF: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1774==    by 0x10AB8C: figura::~figura() (test.cpp:14)
==1774==    by 0x10B155: kolo::~kolo() (test.cpp:20)
==1774==    by 0x10A7B4: main (test.cpp:84)
==1774==  Address 0x4dc1c80 is 0 bytes inside a block of size 32 free'd
==1774==    at 0x483C1CF: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1774==    by 0x10AB8C: figura::~figura() (test.cpp:14)
==1774==    by 0x10B155: kolo::~kolo() (test.cpp:20)
==1774==    by 0x10B175: kolo::~kolo() (test.cpp:20)
==1774==    by 0x10A78B: main (test.cpp:102)
==1774==  Block was alloc'd at
==1774==    at 0x483AE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1774==    by 0x10AAD8: figura::figura(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (test.cpp:8)
==1774==    by 0x10AC27: kolo::kolo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) (test.cpp:25)
==1774==    by 0x10A467: main (test.cpp:84)
==1774== 
==1774== 
==1774== HEAP SUMMARY:
==1774==     in use at exit: 32 bytes in 1 blocks
==1774==   total heap usage: 14 allocs, 14 frees, 74,088 bytes allocated
==1774== 
==1774== 32 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1774==    at 0x483AE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1774==    by 0x10AA29: figura::figura() (test.cpp:7)
==1774==    by 0x10ABE1: kolo::kolo() (test.cpp:24)
==1774==    by 0x10A561: main (test.cpp:88)
==1774== 
==1774== LEAK SUMMARY:
==1774==    definitely lost: 32 bytes in 1 blocks
==1774==    indirectly lost: 0 bytes in 0 blocks
==1774==      possibly lost: 0 bytes in 0 blocks
==1774==    still reachable: 0 bytes in 0 blocks
==1774==         suppressed: 0 bytes in 0 blocks
==1774== 
==1774== For lists of detected and suppressed errors, rerun with: -s
==1774== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
class figura
{
protected:
    string kolor;
public:
    figura() : kolor("nic") {}
    /*explicit*/ figura(const string& s) : kolor(s){}
    virtual ~figura() = default;

    virtual double pole()const = 0;
    virtual void wypisz(ostream& out)const { out<< kolor; }

    friend ostream& operator<<(ostream& out,const figura& r);
};

class kolo:public figura
{
protected:
    unsigned r = 0;
public:
    kolo() : figura(), r(0){}
    kolo(const string& s,const unsigned r):figura(s), r(r){}
    kolo(const kolo& ref) = default;
    kolo& operator=(const kolo& ref) = default;
    double pole()const override { return 3.14*r*r; }
    void wypisz(ostream& out)const override {
        std::out << "Kolor: " << kolor << " " << "Skladowe: " << r << std::endl;
    }
    friend ostream& operator<<(ostream& out,const kolo& r);
};