Realloc()/在C++;对于字符串实现 当它们在内存中表示时,C++对象与C结构相同吗?< /强>

Realloc()/在C++;对于字符串实现 当它们在内存中表示时,C++对象与C结构相同吗?< /强> ,c++,realloc,C++,Realloc,例如,使用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(

例如,使用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);
}
template<int max_size> class MyString
{
public:
   size_t size;
   char contents[max_size];

public:
   MyString(const char* data);
};
<>我不认为C++允许重载<代码> +/Cux>运算符,用于内置的<代码> char */COD>类型。< /P> 因此,我想创建自己的轻量级字符串类,它没有
std::string
所具有的额外开销。我认为
std::string
是连续表示的:

(int)length, (char[])data
我想要完全相同的功能,但不加前缀的长度(节省8字节的开销)

这是我用来测试的代码,但它会导致一个segfault

#include <iostream>
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 << "'";    
}

不能更改C/C++中的对象/结构的大小。它们的大小在编译时是固定的

内存中表示的对象是C++对象,与C结构相同。

严格地说,不是。一般来说,是的。C++类和结构在内存布局与C结构上是相同的,除了:

  • 位字段具有不同的打包规则
  • 大小在编译时是固定的
  • 如果存在任何虚拟函数,编译器将向内存布局添加vtable条目
  • 如果对象继承基类,则新类的布局将附加到基类布局,包括vtable(如果有)
<>我认为C++不允许为内置的char类型重载+运算符。所以我想创建我自己的轻量级string类,它没有额外的开销std::string。我认为std::string是连续表示的

您可以为
char*
类型创建
运算符+
重载。正常行为是指针运算
std::string
重载
operator+
以将
char*
数据附加到字符串中。该字符串作为C字符串以及其他信息存储在内存中。
c_str()
成员函数返回指向内部
char
数组的指针

在C示例中,您依赖于未定义的行为。不要像那样
realloc
。它可能会导致不好的事情,即奇怪的错误

你的C++示例也在做<代码> ReLoLc(这个)中做了坏事。相反,您应该携带一个

char*
并获得一个
new char[]
缓冲区来存储字符,而不是
realloc()
。此类
realloc
的行为未定义

struct myObj {
   //...
   char myVarChar;
};
这行不通。您要么需要一个固定大小的数组,一个指向char的指针,要么使用struct hack。您将无法分配指向此
myVarChar
的指针

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

你指的是什么额外的开销?您是否测试和测量了
std::string
是否真的是一个瓶颈

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

是的,主要是字符缓冲区部分。但是,以下方面:

/* 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;
};
(int)长度(char[])数据

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

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

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;
};

您的类定义/用法有很多错误。如果要存储字符串,应该使用指针类型,比如char*a成员,而不是单个char。使用单个字符意味着只分配一个字符的内存

另一个错误是分配代码,您可以在此代码上执行realloc-您可以潜在地更改分配的内存,但不能更改其值。您必须将结果分配给此以实现此目标(
this=(*pString)realloc(this,strlen(buff+1));
),无论如何,这是一种非常糟糕的做法。在char*成员上使用realloc要好得多


<> P>不幸的是C++ C++有,你必须使用新的和删除,自己做任何拷贝。

为什么你用C类写C,为什么不使用C++?

< p>如果你想要的东西基本上与<代码> STD::String 完全相同,除了它不知道字符串有多长,你应该学习<代码> STD::String 什么操作符重载了它,等等,然后模仿它,只是你想要的差异

然而,这不太可能有任何实际意义

关于您的最新更新,您说您想要一种设计,在这种设计中,通用应用程序代码将传递裸指针到堆对象。没有自动清理


很简单,这是一个非常糟糕的主意。

您不应该浪费时间编写字符串类-人们首先花时间编写字符串类是有原因的,认为他们编写它们是因为他们想创建大的混乱和繁杂的代码,您可以在数小时内轻松改进

例如,对于赋值运算符中的内存重新分配,您的代码具有二次复杂性-每分配一个大于1个字符的sting将使用一个大于1字节的新内存块,从而在“几个”之后产生大内存碎片像这样的分配-您可以节省一些字节,但可能会丢失兆字节来处理空间和内存页碎片

同样以这种方式设计,您也无法有效地实现+=运算符,因为在大多数情况下,您总是需要复制整个字符串,从而在将小字符串多次附加到较大字符串的情况下,再次达到二次复杂度

很抱歉,您的想法很有可能会变得很难维护,并且效率比典型的字符串实现(如std::string)低几个数量级


别担心——这在实践中是正确的“编写您自己的标准容器的更好版本”的所有伟大想法:)

如果您想要性能,您可以编写
class pstring
{
public:
    int myInt;
    char myVarchar;

    void* operator new(size_t size, const char* p);
    void operator delete(void* p); 
};

void* pstring::operator new(size_t size, const char* p)
{
    assert(sizeof(pstring)==size);
    char* pm = (char*)malloc(sizeof(int) + strlen(p) +1 );
    strcpy(sizeof(int)+pm, p);
    *(int*)(pm) = strlen(p);  /* assign myInt */
    return pm;
}

void pstring::operator delete(void* p)
{
    ::free(p);
}


pstring* ps = new("test")pstring;

delete ps;
 #include <iostream>
    using namespace std;
    class pString {
        public:
            char c[1];
            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->c, strlen(buff)+1);
        memcpy(this->c, buff,  strlen(buff));
        *(this->c+strlen(buff)) = '\0';

        return this;
    };

    struct myObj {
            int myInt;
            char myVarChar;
    };

    int main() {

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


This should work. But its not advisable.
#include <iostream>
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() << "'";    
pString myString;
char * charString;
assert(sizeof(myString) == sizeof(charString));
class light_string {
public:
    light_string(const char* str) {
        size_t length = strlen(str);
        char*  buffer = new char[sizeof(size_t) + length + 1];

        memcpy(buffer, &length, sizeof(size_t));
        memcpy(buffer + sizeof(size_t), str, length);
        memset(buffer + sizeof(size_t) + length, 0, 1);

        m_str = buffer + sizeof(size_t);
    }

    ~light_string() {
        char* addr = m_str - sizeof(size_t);
        delete [] addr;
    }

    light_string& operator =(const char* str) {
        light_string s = str;
        std::swap(*this, s);

        return *this;
    }

    operator const char*() {
        return m_str;
    }

    size_t length() {
        return
            *reinterpret_cast<size_t *>(m_str - sizeof(size_t));
    }

private:
    char* m_str;
};


int main(int argc, char* argv[]) 
{
    cout<<sizeof(light_string)<<endl;

    return 0;
}
#include <iostream>
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;

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

    cout << "Address of this After: " << (uint32_t) newPoint << endl;

    return (pString*)newPoint;
};

int main() {

    pString * myString = (pString *) malloc(sizeof(pString));
    *myString = "testing";

    cout << "Address of myString: " << (uint32_t) myString << endl;

    cout << "'" << (char *) myString << "'";    
}
this = (pString*) newPoint;
void concatenate(std::string& s, const char* c) {
    s.reserve(s.size() + strlen(c));
    s.append(c);
}
#include <iostream>
using namespace std;

struct pString {
        /* No Member Variables, the data is the object */ 
        /* This class cannot be extended & will destroy a vtable */
    public:
        pString * pString::operator=(const char *);
};

pString& operator+(pString& first, const char *sec) {


        int lenFirst;
        int lenSec = strlen(sec);
        void * newBuff = NULL;

        if (&first == NULL)
        {
            cout << "NULL" << endl;
            lenFirst = 0; 
            newBuff = malloc(sizeof(pString)+lenFirst+lenSec+1);
        } else {
            lenFirst = strlen((char*)&first);
            newBuff= (pString*)realloc(&first, lenFirst+lenSec+1);
        }

        if (newBuff == NULL)
        {
            cout << "Realloc Failed"<< endl;
            free(&first);
            exit(0);
        }       

        memcpy((char*)newBuff+lenFirst, sec, lenSec);
        *((char*)newBuff+lenFirst+lenSec) = '\0';


        cout << "newBuff: " << (char*)newBuff << endl;

        return *(pString*)newBuff;

};


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

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

    char *newPoint = (char *)realloc(this, strlen(buff)+200);
    memcpy(newPoint, buff,  strlen(buff));
    *((char*)newPoint+strlen(buff)) = '\0';

    cout << "Address of this After: " << (uint32_t) newPoint << endl;

    return (pString*)newPoint;
};


int main() {

    /* This doesn't work that well, there is something going wrong here, but it's just a proof of concept */

    cout << "Sizeof: " << sizeof(pString) << endl;

    pString * myString = NULL;

    //myString = (pString*)malloc(1);
    myString = *myString = "testing";
    pString& ref = *myString;


    //cout << "Address of myString: " << myString << endl;

    ref = ref + "test";
    ref = ref + "sortofworks" + "another" + "anothers";


    printf("FinalString:'%s'", myString);

}
class pString {
    char txt[];
}

class otherString : pString { // This cannot work because now the
    size_t len;               // the flexible array is not at the
}                             // end
class MyConcatString;
class MyString {
public:
  MyString(const MyConcatString& c) {
    reserve(c.l.length()+c.r.lenght());
    operator = (l);
    operator += (r);   
  }
  MyConcatString operator + (const MyString& r) const {
    return MyConcatString(*this, r);
  }
};

class MyConcatString {
public:
  friend class MyString;
  MyConcatString(const MyString& l, const MyString& r):l(l), r(r) {};
  ...
  operator MyString () {
    MyString tmp;
    tmp.reserve(l.length()+r.length());
    tmp = l;
    tmp += r;
    return tmp;
  }
private:
  MyString& l;
  MyString& r;
}
MyString a = "hello";
MyString b = " world";
MyString c = a + b;