当前位置:  开发笔记 > 编程语言 > 正文

Realloc()/在C++中调整对象的大小以实现字符串实现

如何解决《Realloc()/在C++中调整对象的大小以实现字符串实现》经验,为你挑选了3个好方法。

当它们在内存中表示时,C++对象是否与C结构相同?

例如,使用C,我可以这样做:

struct myObj {
       int myInt;
       char myVarChar;
};

int main() {
       myObj * testObj = (myObj *) malloc(sizeof(int)+5);
       testObj->myInt = 3;
       strcpy((char*)&testObj->myVarChar, "test");
       printf("String: %s", (char *) &testObj->myVarChar);
}

我认为C++不允许+为内置char *类型重载运算符.

所以我想创建自己的轻量级字符串类,它没有额外的开销std::string.我认为std::string是连续的代表:

(int)length, (char[])data

我想要完全相同的功能,但没有前缀长度(节省8字节开销).

这是我用来测试的代码,但它导致了段错误

#include 
using namespace std;
class pString {
    public:
        char c;
        pString * pString::operator=(const char *);
};


pString * pString::operator=(const char * buff) {

    cout << "Address of this: " << (uint32_t) this << endl;
    cout << "Address of this->c: " << (uint32_t) &this->c << endl;

    realloc(this, strlen(buff)+1);
    memcpy(this, buff,  strlen(buff));
    *(this+strlen(buff)) = '\0';

    return this;
};

struct myObj {
        int myInt;
        char myVarChar;
};

int main() {

    pString * myString = (pString *) malloc(sizeof(pString));
    *myString = "testing";
    cout << "'" << (char *) myString << "'";    
}

编辑:没有人真正明白我想做什么.是的我知道我可以有一个指向类中字符串的指针,但比普通的cstring贵8个字节,我想要完全相同的内部表示.谢谢你的尝试


编辑:我想要实现的最终结果是能够使用+运算符,与使用strcat等相比没有额外的内存使用量

const char * operator+(const char * first, const char * second);

RnR.. 16

你不应该浪费你的时间来编写字符串类 - 这是人们花时间编写它们的原因,并且认为他们编写它们是天真的,因为他们想要创建大的混淆和过度的代码,你可以在几个小时内轻松改进.

例如,你的代码在赋值运算符中的内存重新分配具有二次复杂度 - 每次分配大于1个字符的sting将使用大于1个字节的新内存块,导致在这样的"少量"赋值后出现大内存碎片 - 你节省了几个字节,但可能会丢失兆字节来解决空间和内存页面碎片问题.

同样以这种方式设计你无法有效地实现+ =运算符,而不是仅仅复制附加的字符串,在大多数情况下你总是需要复制整个字符串 - 因此如果你将一个小字符串附加到一个更大的字符串,那么再次达到二次复杂度一次几次.

抱歉,你的想法看起来有很大的机会变得难以维持,并且比std :: string这样的典型字符串实现的效率低.

别担心 - 这对于"编写自己更好的标准容器版本"的所有好主意来说都是如此":)



1> RnR..:

你不应该浪费你的时间来编写字符串类 - 这是人们花时间编写它们的原因,并且认为他们编写它们是天真的,因为他们想要创建大的混淆和过度的代码,你可以在几个小时内轻松改进.

例如,你的代码在赋值运算符中的内存重新分配具有二次复杂度 - 每次分配大于1个字符的sting将使用大于1个字节的新内存块,导致在这样的"少量"赋值后出现大内存碎片 - 你节省了几个字节,但可能会丢失兆字节来解决空间和内存页面碎片问题.

同样以这种方式设计你无法有效地实现+ =运算符,而不是仅仅复制附加的字符串,在大多数情况下你总是需要复制整个字符串 - 因此如果你将一个小字符串附加到一个更大的字符串,那么再次达到二次复杂度一次几次.

抱歉,你的想法看起来有很大的机会变得难以维持,并且比std :: string这样的典型字符串实现的效率低.

别担心 - 这对于"编写自己更好的标准容器版本"的所有好主意来说都是如此":)



2> dirkgently..:
struct myObj {
   //...
   char myVarChar;
};

这不行.您需要一个固定大小的数组,一个指向char的指针或使用struct hack.您将无法为此指定指针myVarChar.

所以我想创建自己的轻量级字符串类,它没有额外的开销std :: string has.

您指的是多少额外开销?您是否经过测试和测量,看看它std::string是否真的成为瓶颈?

我认为std :: string是连续表示的

是的,主要是字符缓冲部分.但是,以下内容:

(INT)的长度(字符[])的数据

标准不要求.翻译:字符串实现不需要使用其数据的这种特定布局.它可能有额外的数据.

现在,您的轻量级字符串类出现了错误:

class pString {
public:
    char c; // typically this is implementation detail, should be private
    pString * pString::operator=(const char *); 
    // need ctors, dtors at least as well
    // won't you need any functions on strings?
};

尝试以下方面的内容:

/* a light-weight string class */
class lwstring { 
  public:
     lwstring(); // default ctor
     lwstring(lwstring const&); // copy ctor
     lwstring(char const*); // consume C strings as well
     lwstring& operator=(lwstring const&); // assignment
     ~lwstring(); // dtor
     size_t length() const; // string length
     bool empty() const; // empty string?
  private:
     char *_myBuf;
     size_t _mySize;
};



3> Mark Ransom..:

哇.你要做的是彻底滥用C++,如果它有效的话,完全依赖于编译器,并且肯定会让你有一天在TheDailyWTF中登陆.

你得到段错误的原因可能是因为你的operator =将对象重新分配到不同的地址,但是你没有更新main中的myString指针.我甚至在这一点上甚至称它为一个对象,因为从未调用任何构造函数.

我认为你要做的是让pString成为一个更聪明的指向字符串的指针,但是你会发现它错了.让我来解决一下.

#include 
using namespace std;
class pString {
    public:
        char * c;
        pString & operator=(const char *);
        const char * c_str();
};


pString & pString::operator=(const char * buff) {

    cout << "Address of this: " << (uint32_t) this << endl;
    cout << "Address of this->c: " << (uint32_t) this->c << endl;

    c = (char *) malloc(strlen(buff)+1);
    memcpy(c, buff,  strlen(buff));
    *(c+strlen(buff)) = '\0';

    return *this;
};

const char * pString::c_str() {
    return c;
}

int main() {

    pString myString;
    myString = "testing";
    cout << "'" << myString.c_str() << "'";    

}

现在我不会使用malloc而是使用new/delete,但我保留了尽可能接近原始的内容.

可能会认为你在你的课堂上浪费了一个指针的空间,但你不是 - 你正在为你以前保留在主要指针中的指针进行交易.我希望这个例子说清楚 - 变量大小相同,malloc/realloc分配的额外内存量也是一样的.

pString myString;
char * charString;
assert(sizeof(myString) == sizeof(charString));

PS我应该指出,这段代码仍然需要很多工作,它充满了漏洞.你需要一个构造函数来初始化指针,一个析构函数可以在它完成时释放它,只是为了初学者.你也可以自己实现operator +.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有