【问题标题】:C++ My String class: Pointer doesn't workC++ 我的字符串类:指针不起作用
【发布时间】:2013-10-21 01:58:02
【问题描述】:

我正在用 c++ 11 构建自己的字符串类,但我遇到了内存问题。

主要:

MyString str1;     //Works ok, constructor creates empty char array.
const char* pointer1 = str1.c_str(); //Return the pointer to the array.
str1.Reserve(5); 

// Now, when I use the Reverse method in string1, Pointer1 is 
// pointing to the old memory address.

如何将str1中的数组数据改为内存地址?

换句话说,我该如何解决这个问题:

pointer1 == str1.c_str();

预留方式:

void reserve(int res)
{
    capacity = NewSize(size + res,0 , capacity); //Method to find the best cap.

    char* oldData = data;

    data = new char[capacity];
    memcpy(data, oldData, capacity);
    oldData = data;
    //delete[] data;

    data[(size)] = '\0';
}

这会返回所有正确的数据,但是当我执行“oldData = data”时,内存地址会丢失。

感谢所有帮助,谢谢!

【问题讨论】:

  • 既然oldData 应该指向之前的位置,为什么要重新分配data 的值而不是delete[] oldData
  • 你为什么要这样做:const char* pointer1 = str1.c_str();str1.Reserve(5);?除非您打算承诺 str1.c_str() 永远不会改变,否则这是行不通的。您的用户必须注意,对字符串的更改可能会导致对指针的更改,并且只能在保证字符串对象不会更改的范围内使用 c_str() 的返回值。
  • c_str() documentation 清楚地表明这是未定义的行为。
  • 在 Reserve 方法中,data 是 char*。我要做的是: 1. 将旧数据保存在 OldData 2. 在 Data 上使用 new 创建一个新数组。 (这是地址丢失的地方) 3. 将旧数据复制到新数据中。
  • Egads,一句话,你不能。

标签: c++ pointers memory-management c++11 operator-overloading


【解决方案1】:

我认为您要问的是是否有一种方法可以从您的字符串类中获取返回值,该返回值将始终指向当前的字符串数组。有很多方法可以做到这一点,但通常这表明设计/实现不佳。

更正常的做法是告知 API 用户 c_str() 的结果会因对象的任何后续修改而失效:不要保留指针,只需再次调用 c_str()。

两个明显的选择是:a) 一个指向指针的指针,非常危险,因为现在你的类之外的人可以调整它,b) 提供一个封装类,它封装一个指向指针的指针,不允许修改。

template<typename T>
struct ReadOnlyPointer {
    T* m_ptr;
    ... operator * ...
    ... operator -> ...
    ... operator T ...
};

ReadOnlyPointer<const char*> pointer = str1.pointer();

您的“保留”功能似乎也至少存在一些问题。

  1. 即使大小可能为零,您也可以在 data[0] 处推送一个 '\0'。

    我的字符串 a; a. 保留(0); // 碰撞?您写入了零长度数组的第一个字节。

  2. 在将数据从 oldData 复制到 data 后,出于某种原因,您将 'data' 的值分配给 'oldData',然后再不使用 'oldData' - 这是内存泄漏。

  3. 您的 memcpy 使用“容量”而不是“大小”,因此可能会过度复制。

请考虑:

// ensure we have an additional 'res' bytes.
// caution: unlike stl and boost reserve, these are
// additional bytes, not total bytes.
void reserve(int res)
{
    int newCapacity = NewSize(m_size + res, 0, m_capacity); //Method to find the best cap.
    if(newCapacity <= m_capacity)
        return;

    char* newData = new char[newCapacity];
    memcpy(newData, m_data, m_size);
    delete[] m_data;        // release the old allocation
    m_data = newData;
    m_capacity = newCapacity;
}

如果您没有在代码中的其他位置更改 size 的值,额外的 data[(size)] = '\0'; 可能会导致您的字符串被截断。

【讨论】:

  • 感谢您抽出宝贵时间对此进行解释。我发现我误解了 c_str() 的含义,并且了解了更多关于指针的知识。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
相关资源
最近更新 更多