【问题标题】:Memory deallocation of temporary object c++临时对象c ++的内存释放
【发布时间】:2018-01-01 13:47:03
【问题描述】:

我构建了一个简单的字符串类。 我尝试制作连接函数,其中一个是+,另一个是+=。 在尝试实现+= 时,我在其下生成了一个Str 对象,该对象等于第一个字符串,其大小为s.size()。但是当我尝试向它附加一个新字符串 t 时,我需要释放旧数组 s 字符串并为其分配新大小。在调用 temp Str 对象的析构函数后,它在释放旧空间时卡在那里,我不明白为什么。如何释放+ 成员函数下的Str

class Str
{

public:
    typedef size_t size_type;
    typedef char* iterator;
    typedef const char* const_iterator;
    iterator begin(){ return p; }
    iterator end() { return p + std::strlen(p); }
    const_iterator begin() const { return p; }
    const_iterator end() const { return p + std::strlen(p); }

    size_type size() const { return data_length; }
    Str() {};


    Str(const Str& s): 
        p(new char[s.size() +1]), 
        data_length(s.size())
    {
        std::copy(s.begin(), s.end(), p);
        p[data_length] = '\0';
    }

    Str(const char* cp) :
        p(new char[std::strlen(cp) + 1 ]), 
        data_length(std::strlen(cp))
    {
        std::copy(cp, cp+ std::strlen(cp) + 1,p);//copies also the '\0' char to the last place in p
    }


Str& operator=(Str& rhs)//assignment operator
{
    if (&rhs != this)
    {
        uncreate();
        create(rhs.size());
        std::copy(rhs.begin(), rhs.end() + 1, p);
        //p[rhs.size()] = '\0';
    }
    return *this;
}

Str& operator=(const char* cp)//assignment operator
{
    if (cp!= p)
    {
        uncreate();
        create(std::strlen(cp));
        std::copy(cp, cp+std::strlen(cp), p);
        p[data_length] = '\0';
    }
    return *this;
}




    Str& operator+=(const Str&);

    ~Str() 
    {
        delete[] p;//stucked here while returning from + member function
        data_length = 0;
    }

    const char* c_str() const;
    void copy(char* ,size_type);
private:
    char* p;
    size_type data_length = 0;

    const_iterator ci() const { return p; }

    void uncreate();
    void create(size_type);
};



Str operator+(const Str& s, const Str& t)
{
    Str r = s;
    r += t;
    return r;   

}


inline Str& Str::operator+=(const Str &s)
{
    //trying to allocate new space for this object 

    std::copy(s.begin(),s.end(),p+this->size());
    p[data_length] = '\0';
    return *this;
}

void Str::create(Str::size_type n)
{
    p = new char[n + 1];
    data_length = n;
}

void Str::uncreate()
{
    delete[] p;//to check that p is allocated right
    data_length = 0;
}

main 为例:

int main()
{

    Str s1 = "hello"; 
    Str s2 = "worly";
    Str s3 = s1 + s2;

    return 0;
}

【问题讨论】:

  • 你只是don't!使用std::string instread。
  • 我尝试释放r 对象?我可以这样做吗?
  • 像你一样在析构函数中这样做有什么问题?
  • 如果这是用于生产工作,请使用 std::string。如果这是一个教育练习,您应该在代码中准确地一个调用 strlen - 在来自const char* 的构造函数中,以初始化datalen。其他所有呼叫都应使用datalen。 (这样,您的字符串 - 如 std::string - 可以包含嵌入的 nul 字符。)
  • @axcelenator :您不需要释放器。运算符 + 中 r 的析构函数将执行释放。当然,在operator +=,你需要1.分配足够的内存。 2. 从旧内存中复制初始部分。 3. 从 rhs 复制附加的字符串。 4. 释放旧内存。 5.将指针存储在this->p中(第3步需要在第4步之前,以防有人这样做s+=s

标签: c++ memory-management concatenation


【解决方案1】:

我想你想要这样的东西:

inline Str& Str::operator+=(const Str &s)
{
    const int new_data_length = data_length + s.data_length;
    char * temp = new char[new_data_length + 1];
    memcpy(temp, p, data_length);
    memcpy(temp + data_length, s.p, s.data_length);

    delete [] p;
    p = temp;

    data_length = new_data_length;
    p[data_length] = 0;

    return *this;
}

【讨论】:

  • @p-a-o-l-o hello 当从+ 运算符返回时析构函数中的 delete[] 运算符停止程序
  • 在从s.p 复制之前,您不得删除旧的p - 它们可能是同一个变量 (s += s;)
  • @MartinBonner - 很好,当我评论用 temp 替换 p 时没有想到这一点,虽然我认为这个概念仍然适用,将所有内容复制到 temp 然后一旦所有复制完成完成,删除p,然后将temp 分配给p。不需要额外的复制返回步骤。
  • 分配给p后,您不能delete [] temp
  • 感谢评论者。也许,我今天根本不应该发帖:)
猜你喜欢
  • 2011-10-28
  • 2016-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多