Does the boost::hold_any constructor have undefine

2019-07-08 09:05发布

问题:

I looked through the boost::hold_any file and I found something what confuses me. if I consider the informations I got through the answers to my question: What happens if you call a destructor and use the allocated memory again for other objects? (In the answer by Mike Seymour) then it is "forbidden" to manipulate the memory of an object which weren't released and reallocated yet, to place there a new object of a different type.

I always thought the boost library sticks to the standard, but if I'm not total wrong then boost::hold_any stores small objects or variables inside the memory of it's content pointer (void* object) itself, which would break the rule I found in the previously mentioned answer.

So am I total wrong or does boost::hold_any breaks the standard? And if I'm wrong, where is my mistake?

Or if I'm right, how reliable are the boost libraries if they contain parts, which could cause undefined behavior?

Well, I know that the boost developers normally know what they are doing, but I hear so often undefined behavior has to be avoided under all conditions so I'm a bit curious.

EDIT I changed the code example to show, the old content definitly is destroyed!

This is one of the points in the boost::hold_any code where I got my information from:

    template <typename T>
    basic_hold_any& assign(T const& x)
    {
        // are we copying between the same type?
        spirit::detail::fxn_ptr_table<Char>* x_table =
            spirit::detail::get_table<T>::template get<Char>();
        if (table == x_table) {
        // if so, we can avoid deallocating and re-use memory
            table->destruct(&object);    // first destruct the old content
            if (spirit::detail::get_table<T>::is_small::value) {
                // create copy on-top of object pointer itself
                new (&object) T(x);
            }
            else {
                // create copy on-top of old version
                new (object) T(x);
            }
        }
        else {
            if (spirit::detail::get_table<T>::is_small::value) {
                // create copy on-top of object pointer itself
                table->destruct(&object); // first destruct the old content
                new (&object) T(x);
            }
            else {
                reset();                  // first delete the old content
                object = new T(x);
            }
            table = x_table;      // update table pointer
        }
        return *this;
    }

回答1:

In the linked answer, the UB is that base* ptr is used while it still points to that storage after placement new was called and a different object of a different type has been created there (it is used to call delete on it). This is not the case in Boost Any. Reusing the storage is not UB in itself.