Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamically sized classes in c++

I'd like to create a class Word, which houses a word. I'll have an instance of the class for pretty much every word in the dictionary (so lots) -- and no, I cannot use a tree structure to store this for my particular application. Of course, the size of the strings may vary, and I don't want to kill memory. I'd like to do this in a class, as so:

class Word {
    public:
        ...
    private:
        int         len;
        LetterData  letters[];
};

And then dynamically allocate Word using:

Word *pNewWord = malloc(sizeof(Word)+sizeof(LetterData)*len);   

I realize this isn't very C++'ish. So my questions are: first, is there a better way of doing this, and if not, is this going to cause problems? Word will not inherit any other class types (I'm fairly certain that inheritance would kill this...).

Note: memory usage and speed are very important -- I'd like to avoid an extra pointer per word, and I'd like to avoid an extra pointer deference per access...

like image 290
user2766918 Avatar asked Oct 16 '17 12:10

user2766918


Video Answer


2 Answers

My starting point would be to build what would be, for now, little more than a proxy class for std::string:

class Word
{
public:
    std::size_t getSize() const; // in place of your 'len' member.

private:
    std::string m_data;
};

I would then build the rest of my program and only then if there is a performance issue with my Word class cf. other areas of the program would I attempt to refactor it, replacing m_data with something else.

My money is on that being unnecessary and your suspicions around the C++ standard library objects not having adequate performance unfounded.

like image 160
Bathsheba Avatar answered Oct 05 '22 03:10

Bathsheba


Using open sized array as the last member of struct is quite common practice in C. And it was standardized in C99 (2.6.7."flexible array member").

C++ standard says nothing about "flexible array members". So it is not guarantee that it works in C++. But the most of the popular compilers support this feature even for C++:

  • gcc
  • msvc
  • clang "Note that clang does support flexible array members (arrays with a zero or unspecified size at the end of a structure)"

So actually it is possible to use it, but this is very dangerous practice. You should try to avoid it, and you need to be very careful if you decide to use it.

There are several potential issues if you are using this technique:

  • Any reallocation or deletion of memory buffer makes your object invalid.
  • Your class must be non-copyable. Any copy (usually implicit copy when you pass your object as an argument) makes the object invalid. You must forbid copy constructor and assignment operator.
  • Inheritance is not possible, you must forbid it.
  • You should initialize all data correctly to avoid garbage (maybe fill buffer with zeros and than use placement new operators)
  • This method is often used for serialization, saving and restoring the objects, but it is not portable. You need to think about sizes of members and big/little endians.

So if it is possible it is better to use something else. The solution with for example vector of LetterData as a member of class.

like image 35
Sandro Avatar answered Oct 05 '22 01:10

Sandro