Variable Sized Struct C++

前端 未结 10 1066
忘掉有多难
忘掉有多难 2020-11-30 04:48

Is this the best way to make a variable sized struct in C++? I don\'t want to use vector because the length doesn\'t change after initialization.

struct Pack         


        
相关标签:
10条回答
  • 2020-11-30 05:25

    There's nothing whatsoever wrong with using vector for arrays of unknown size that will be fixed after initialization. IMHO, that's exactly what vectors are for. Once you have it initialized, you can pretend the thing is an array, and it should behave the same (including time behavior).

    0 讨论(0)
  • 2020-11-30 05:28

    You can use the "C" method if you want but for safety make it so the compiler won't try to copy it:

    struct Packet
    {
        unsigned int bytelength;
        unsigned int data[];
    
    private:
       // Will cause compiler error if you misuse this struct
       void Packet(const Packet&);
       void operator=(const Packet&);
    };
    
    0 讨论(0)
  • 2020-11-30 05:28

    There are already many good thoughts mentioned here. But one is missing. Flexible Arrays are part of C99 and thus aren't part of C++, although some C++ compiler may provide this functionality there is no guarantee for that. If you find a way to use them in C++ in an acceptable way, but you have a compiler that doesn't support it, you perhaps can fallback to the "classical" way

    0 讨论(0)
  • 2020-11-30 05:31

    I'd probably just stick with using a vector<> unless the minimal extra overhead (probably a single extra word or pointer over your implementation) is really posing a problem. There's nothing that says you have to resize() a vector once it's been constructed.

    However, there are several The advantages of going with vector<>:

    • it already handles copy, assignment & destruction properly - if you roll your own you need to ensure you handle these correctly
    • all the iterator support is there - again, you don't have to roll your own.
    • everybody already knows how to use it

    If you really want to prevent the array from growing once constructed, you might want to consider having your own class that inherits from vector<> privately or has a vector<> member and only expose via methods that just thunk to the vector methods those bits of vector that you want clients to be able to use. That should help get you going quickly with pretty good assurance that leaks and what not are not there. If you do this and find that the small overhead of vector is not working for you, you can reimplement that class without the help of vector and your client code shouldn't need to change.

    0 讨论(0)
  • 2020-11-30 05:36

    If you are truly doing C++, there is no practical difference between a class and a struct except the default member visibility - classes have private visibility by default while structs have public visibility by default. The following are equivalent:

    struct PacketStruct
    {
        unsigned int bitlength;
        unsigned int data[];
    };
    class PacketClass
    {
    public:
        unsigned int bitlength;
        unsigned int data[];
    };
    

    The point is, you don't need the CreatePacket(). You can simply initialize the struct object with a constructor.

    struct Packet
    {
        unsigned long bytelength;
        unsigned char data[];
    
        Packet(unsigned long length = 256)  // default constructor replaces CreatePacket()
          : bytelength(length),
            data(new unsigned char[length])
        {
        }
    
        ~Packet()  // destructor to avoid memory leak
        {
            delete [] data;
        }
    };
    

    A few things to note. In C++, use new instead of malloc. I've taken some liberty and changed bitlength to bytelength. If this class represents a network packet, you'll be much better off dealing with bytes instead of bits (in my opinion). The data array is an array of unsigned char, not unsigned int. Again, this is based on my assumption that this class represents a network packet. The constructor allows you to create a Packet like this:

    Packet p;  // default packet with 256-byte data array
    Packet p(1024);  // packet with 1024-byte data array
    

    The destructor is called automatically when the Packet instance goes out of scope and prevents a memory leak.

    0 讨论(0)
  • 2020-11-30 05:40

    This is OK (and was standard practice for C).

    But this is not a good idea for C++.
    This is because the compiler generates a whole set of other methods automatically for you around the class. These methods do not understand that you have cheated.

    For Example:

    void copyRHSToLeft(Packet& lhs,Packet& rhs)
    {
        lhs = rhs;  // The compiler generated code for assignement kicks in here.
                    // Are your objects going to cope correctly??
    }
    
    
    Packet*   a = CreatePacket(3);
    Packet*   b = CreatePacket(5);
    copyRHSToLeft(*a,*b);
    

    Use the std::vector<> it is much safer and works correctly.
    I would also bet it is just as efficient as your implementation after the optimizer kicks in.

    Alternatively boost contains a fixed size array:
    http://www.boost.org/doc/libs/1_38_0/doc/html/array.html

    0 讨论(0)
提交回复
热议问题