开发者

would the pointer returned by new(size, value) Type[0] be legal and could it be used to build an array?

开发者 https://www.devze.com 2023-02-22 21:17 出处:网络
The standard says, in 5.3.4[expr.new]/7 When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

The standard says, in 5.3.4[expr.new]/7

When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

and in 3.7.3.1[basic.stc.dynamic.allocation]/2

The effect of dereferencing a pointer returned as a request for zero size is undefined.

But if the allocation function is user-defined and it knows it returned a valid pointer, would it still be undefined behavior to dereference it? Can the standard mandate undefined behavior of user code?

The reason I ask is yet another meaningless attempt to initialize a dynamic array of objects of non-default-constructible type. What problems does it have, besides the obvious lack of delete[] and that it can only be called with [0]? Did I even use aligned_storage correctly?

#include <type_traits>
#include <stdexcept>
#include <memory>
#include <iostream>

struct T {
   int val;
   T() = delete;
   T(int i) : val(i) {}
   void* operator new[](std::size_t, std::size_t cnt, const T& t)
   {
       typedef std::aligned_storage<sizeof(t),
                    std::alignment_of<T>::value>::type buf;
       T* ptr = reinterpret_cast<T*>(new buf[cnt]);
       std::uninitialized_fill_n(ptr, cnt, t);
       return ptr;
    }
};

int main()
{
    T* a = new(100, T(7)) T[0]; // using zero is legal per 5.3.4/7

    std::cout << "a[0] = " << a[0].val << '\n' // but is this legal?
              << "a[1] =开发者_如何学C " << a[1].val << '\n'
              << "a[98] = " << a[98].val << '\n'
              << "a[99] = " << a[99].val << '\n';
    delete[] a; // free the 100 aligned_storages
}

test run: http://ideone.com/iBW0z

also compiles and runs as expected with with MSVC++ 2010 EE


There's an irritating logic problem in your code:

The new expression:

T* a = new(100, T(7)) T[0];

Calls T's deleted default constructor [expr.new]/17. ;-(

std::vector<T> is sure looking good about now... :-)


The only non-undefined behavior of the use of the result of a reinterpret_cast is when the cast is back to its original type, so you already have UB there even if everything else was ok.

If you really need this, why don't you just make a function that allocates a large enough block of contiguous memory and then placement news a bunch of T into that memory?

0

精彩评论

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