自定义字符串实现中 c_str() 函数中的恒常性问题

Constness problems in c_str() function in custom string implementation

本文关键字:函数 常性 问题 str 实现 字符串 自定义      更新时间:2023-10-16

C++来说还是新的。我正在尝试实现c_str()函数。我试过了:

class Str
{
public:
    typedef size_t size_type;
    typedef char* iterator;
    typedef const char* const_iterator;
const char* c_str() const {
    char* tmp = alloc.allocate(length + 1);
    alloc.construct(tmp + length + 1, '');
    for(size_type i = 0; i < length; ++i)
        tmp[i] = data[i];
    return tmp;
}
private:
    char* data;
    size_type length;
    std::allocator<char> alloc;
};

但是我的编译器在抱怨。似乎,由于将函数定义为 const,allocate() 必须返回常量指针(或者我弄错了什么)。无论如何,这是行不通的,我想知道是什么情况。

1)我知道我调用allocate(),但我在新变量上调用它,而不是Str的成员。这就是为什么我没有得到那部分。
2)我知道"返回数据",但我想知道为什么这不起作用。在 C++11 中,c_str() 和 data() 之间没有区别,但假设仍然存在:如果我总是做"返回数据",我将如何区分这两者?

所有已知的 std::string 实现c_str()方法是为 data 中的一个附加字符保留空间,并始终保持 null 终止,以便c_str()只是简单地return data;,并且保证已经以 null 结尾。

似乎,由于将函数定义为 const,allocate() 必须返回常量指针(或者我弄错了什么)。

不,你肯定搞错了什么。

代码中的问题是alloc在该成员函数中是常量。您可以通过创建分配器的非常量副本来解决它:

const char* c_str() const {
    std::allocator<char> alloc2(alloc);
    char* tmp = alloc2.allocate(length + 1);
    alloc2.construct(tmp + length + 1, '');
    for(size_type i = 0; i < length; ++i)
        tmp[i] = data[i];
    return tmp;
}

这并不能使函数正确,因为它每次调用它时都会分配内存,因此调用者必须使用 std::allocator<char> 释放它,这不是c_str()的正确接口!

注意:使用std::allocator<char>::construct是完全没有意义的,你不妨只做tmp[length] = ''。即使使用std::allocator<char>也毫无意义,你可以只使用newdelete[]。使用分配器的原因是允许用户使用替代分配器对其进行自定义,但是如果您只是将其修复为仅使用std::allocator<char>那么使用分配器根本没有真正的优势,您只是让您的类占用更多空间来存储毫无意义的alloc成员。

另外,这不应该tmp + length吗?

    alloc.construct(tmp + length + 1, '');

回答编辑的问题

1)我知道我调用allocate(),但我在新变量上调用它,而不是Str的成员。这就是为什么我没有得到那部分。

呃,不,你

没有,你叫会员!

2)我知道"返回数据",但我想知道为什么这不起作用。在 C++11 中,c_str() 和 data() 之间没有区别,但假设仍然存在:如果我总是做"返回数据",我将如何在这两者之间做出区分?

你为什么要在两者之间有所作为?

C++03 并没有说两者之间必须有区别,它们是一致的,c_str()data() 在 C++11 中完全相同的原因之一是,无论如何,所有实现在 C++03 中都是这样做的。这真的是唯一理智的方法。

缘无故地使它们与众不同只会使实现c_str()变得极其困难,因此是一个非常愚蠢的设计选择。

为什么不将数据作为常量字符*返回? 没有人可以改变它,因为它是恒定的。

const char* c_str() const{
   return data;
}