There is no simple answer to this question.
A single object? Some run time determined quantity?
Is the object created every loop or recursive call?
Because stack overflows can be difficult to recognize, all these choices can influence how careful you want to be when choosing to put a big object on the stack.
In the embedded systems I have worked on, stack vs heap was seldom discussed. Instead, the issue was simply "what is the lifetime of the object".
And, perhaps surprisingly, most of the 'important' objects were created at start-up, and never destructed. i.e. they lasted until the system was reset or powered down.
In that embedded environment, the important objects were in the heap.
Of course, in a substantial system, there were also many objects that only lasted to the end of a function (or method).
These short term objects would either fit (or not) into the stack associated with the single thread using them. There was no run-time stack size change mechanism (that I knew of) in that version of vxWorks. Each task (which I think correspond to linux threads) had a stack size determined at compile time. And we did, on occasion, overflow the stack.
When you discover and convince yourself you have stack overflow in your program, there are 2 solutions (or maybe more)
In one particular case, my team's decision was to expand the specific threads stack size. The overflow was unique to that thread.
In several others, we new'd the object to the heap at the beginning of the function, and deleted it at exit. Simple, right?
Is that the only two choices? Maybe.
So, if you have to have a number, I would say look for someone's else's rule-of-thumb.
As a practiced developer of embedded systems, I would describe my choices as:
I keep non-trivial objects on the heap.
small quantities of any comparatively simple objects on the stack.
life-time issues can only push things from stack to the heap
bigger size can only push things from stack to the heap
Personally, I am very comfortable using new and delete, and have opinions about ownership issues. However ... my 'style' choices are not for every one. And there is a lot of literature suggesting that, ultimately, complexity will confuse any knowledge of what task owns what objects (and thus which task should delete which objects)
Now, figure out what you mean by non-trival, and simple.
With respect to std::vector, and std::strings, std::stringstream, and map's, well these are all relatively complex objects (IMHO).
But if you use sizeof(), they are surprisingly small, even when filled. I think this implies that these are each a 'front end' for heap access.
On the other hand, they perform well, and perhaps are doing something else, (not heap related) But I have not looked into it.
More to learn.