开发者

Is there any case for which returning a structure directly is good practice?

开发者 https://www.devze.com 2023-04-07 18:51 出处:网络
IMO all code that returns structure directly can be modified to return 开发者_如何转开发pointer to structure.

IMO all code that returns structure directly can be modified to return 开发者_如何转开发pointer to structure.

When is returning a structure directly a good practice?


Modified how? Returning a pointer to a static instance of the structure within the function, thus making the function non-reentrant; or by returning a pointer to a heap allocated structure that the caller has to make sure to free and do so appropiately? I would consider returning a structure being the good practice in the general case.


The biggest advantage to returning a complete structure instead of a pointer is that you don't have to mess with pointers. By avoiding the risks inherent with pointers, especially if you're allocating and freeing your own memory, both coding and debugging can be significantly simplified.

In many cases, the advantages of passing the structure directly outweigh the downsides (time/memory) of copying the entire structure to the stack. Unless you know that optimization is necessary, no reason not to take the easier path.


I see the following cases as the ones I would most commonly opt for the passing structs directly approach:

  • "Functional programming" style code. Lots of stuff is passed around and having pointers would complicate the code a lot (and that is not even counting if you need to start using malloc+free)

  • Small structs, like for example

    struct Point{ int x, y; };
    

    aren't worth the trouble of passing stuff around by reference.


And lastly, lets not forget that pass-by-value and pass-by-reference are actually very different so some classes of programs will be more suited to one style and will end up looking ugly if the other style is used instead.


These other answers are good, but I think missingno comes closest to "answering the question" by mentioning small structs. To be more concrete, if the struct itself is only a few machine words long, then both the "space" objection and the "time" objection are overcome. If a pointer is one word, and the struct is two words, how much slower is the struct copy operation vs the pointer copy? On a cached architecture, I suspect the answer is "none aat all". And as for space, 2 words on stack < 1 word on stack + 2 words (+overhead) on heap.

But thes considerations are only appropriate for specific cases: THIS porion of THIS program on THIS architecture.

For the level of writing C programs, you should use whichever is easier to read.


If you're trying to make your function side-effect free, returning a struct directly would help, because it would effectively be pass-by-value. Is it more efficient? No, passing by reference is quicker. But having no side effects can really simplify working with threads (a notoriously difficult task).


There are a few cases where returning a structure by value is contra-indicated:

1) A library function that returns 'token' data that is to be re-used later in other calls, eg. a file or socket stream descriptor. Returning a complete structure would break encapsulation of the library.

2) Structs containing data buffers of variable length where the struct has been sized to accommodate the absolute maximum size of the data but where the average data size is much less, eg. a network buffer struct that has a 'dataLen' int and a 'char data[65536]' at its end.

3) Large structs of any typedef where the cost of copying the data becomes significant, eg:

a) When the struct has to be returned through several function calls - multiple copying of the same data.

b) Where the struct is subsequently queued off to other threads - wide queues means longer lock times during the copy-in/copy-out and so increased chance of contention. That, and the size of the struct is inflicted on both producer and consumer thread stacks.

c) Where the struct is often moved around between layers, eg. protocol stack.

4) Where structs of varying def. are to be stored in any array/list/queue/stack/whateverContainer.

I suspect that I am so corrupted by c++ and other OO languages that I tend to malloc/new almost anything that cannot be stored in a native type

Rgds, Martin

0

精彩评论

暂无评论...
验证码 换一张
取 消