0

C/C++ have multiple ways to allocate memory at compile time. For example, I can add a global or static variable. The memory to store the value is allocated at compile time:

int x;
// -- or --
void f() {
    static int y;
}
// -- or --
class C {
    static int z;
};
int C::z;

But this solutions can't be used to allocate memory "inline". Is there a possibility to do something like the following in one line?

static int value_behind_x; // does not need to be "named"
int * const x = &value_behind_x;

I mean something that looks like this:

int * const x = static_new int;
// -- or --
int * const x_array = static_new int[10];

I know about one thing in C/C++ that allows something like this: string literals. However, they must be constant and they don't allow specifying the size as number.

If there is no such way, is there a reason for that or may it be implemented in the future? It would be nice because it would make it possible to implement a constexpr version of containers like std::vector.

JojOatXGME
  • 3,023
  • 2
  • 25
  • 41
  • 4
    Choose C or C++ – Eugene Sh. Jan 18 '17 at 14:59
  • 2
    Isn't `std::array` a kind of "constexpr vector"? – Kerrek SB Jan 18 '17 at 15:00
  • 1
    Sounds like you might be looking for placement new if you are using C++. – NathanOliver Jan 18 '17 at 15:00
  • @KerrekSB I know `std::array` but it requires to specify the size as template argument. The size should not be part of the type. It should even be possible to change pointer in a way that it point to memory that was allocated dynamically. – JojOatXGME Jan 18 '17 at 15:05
  • @JojOatXGME write your own template function `joj_new()` which would create object in static or dynamic data as you need. You have to preallocate static memory though. – Slava Jan 18 '17 at 15:07
  • @JojOatXGME What is the point of having an array with out size? And it's not part of the type. It's a const member of a const data structure, which seems what you want to have in here `int * const x_array = static_new int[10];` – luk32 Jan 18 '17 at 15:07
  • @NathanOliver No, I want allocate memory at compile time. For example from data section. Placement new does not allocate memory. It constructs an object on memory that was previously allocated. – JojOatXGME Jan 18 '17 at 15:08
  • What's the difference between your `int * const x = static_new int;` and `static int y;` and using `&y` in place of `x`? – Kevin Jan 18 '17 at 15:09
  • @Slava Im not sure whether this works as `constexpr` if you use it more than one time because you have to save the state between function calls. Furthermore, it would be error-prone to preallocate the right amount of memory. – JojOatXGME Jan 18 '17 at 15:12
  • You could always use std::vector with an arena allocator pointing to a static arena. It wouldn't be constexpr because the allocator interface isn't, but it'd be close enough. – Kerrek SB Jan 18 '17 at 15:12
  • " it would be error-prone to preallocate the right amount of memory" then you are out of luck - you have to preallocate static memory, that's how it works. – Slava Jan 18 '17 at 15:14
  • @Kevin The difference between `&value_behind` and `static_new int` is, that the second one does not need a static object before. This means I can use and return a new storage/pointer in each call of a `constexpr`-function. – JojOatXGME Jan 18 '17 at 15:17
  • @JojOatXGME then what's the difference between `int* const x = get_static_int(); int* const y = get_static_int();` and `static int x; static int y;`? Anywhere you need a pointer to static data you can just use the static data instead. – Kevin Jan 18 '17 at 15:20
  • @KerrekSB This could work. But something like `static_new` would make it simpler to read and write. It would also make it possible while using less code and redundancy. Maybe it would be a nice feature but it seems no to be there yet. Thanks for your help. – JojOatXGME Jan 18 '17 at 15:27
  • @Kevin Sure, you can do it in this simple case but software might be more comlex. For example, you may have a static list of data that is initialized with some values at compile-time. You could preallocate the data within an array but it may make the code less readable then specifying it inline. Furthermore, you may process the input first. You could preallocate the input but you don't know the size of data you need. For example, you may want a function that parses a regex at compile time. You know the size of compiled data in constructor only. This means the constructor have to allocate ist. – JojOatXGME Jan 18 '17 at 15:47
  • Possible duplicate of [Array Equivalent of Bare-String](http://stackoverflow.com/questions/29394937/array-equivalent-of-bare-string) – Jonathan Mee Jan 18 '17 at 18:05

3 Answers3

2

Your statement that static will:

Allocate memory at compile time

This indicates a misconception. Static Storage Durration is defined:

The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern.

Understanding Static Storage Duration is essential to combating the "static initialization fiasco".

With that understanding we can see that there is no performance benefit to constructing a static pointer to a variable, such as static unique_ptr<const int> x(new int(13)); Instead just using the address of value_behind_x as necessary is preferable.

The same thing applies to allocating an array with Static Storage Duration. You could use a container such as array if you need container encapsulation of your array: static array<int, 10> x_array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } But generally speaking with the improvements to range access and container access provided by , , and in the iterator library I'd just suggest that you stick with:

static const x_array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

EDIT:

Just so you are aware, string literals also have Static Storage Duration, meaning that thy are not "allocated at compile time." In fact There are only 3 storage durations other than Static Storage Duration used by C++:

  • Automatic Storage Duration. The object is allocated at the beginning of the enclosing code block and deallocated at the end. All local objects have this storage duration, except those declared static, extern or thread_local.
  • Thread Storage Duration. The object is allocated when the thread begins and deallocated when the thread ends. Each thread has its own instance of the object. Only objects declared thread_local have this storage duration. thread_local can appear together with static or extern to adjust linkage.
  • Dynamic Storage Duration. The object is allocated and deallocated per request by using dynamic memory allocation functions.

So no, there is no allocation or initialization before runtime. Nor do I expect there to ever be, as that would require a fundamental C++ ideology change and a computer architectural change at some level.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • I know that `static std::vector x = {a, b, c}` will allocate memory at runtime before calling `main()`. However, with something like `static_new`, it would be possible to implement of version of `std::vector` that can handle such situations without allocating and initializing memory at runtime. It would have a teeny overhead at destruction only since it must check wether the memory is static or not. Maybe an implementation would also need an alternativ keyword for `constexpr` that allows execution at compile-time only (not both). – JojOatXGME Jan 18 '17 at 15:59
  • @JojOatXGME Ah so you're asking this: http://stackoverflow.com/questions/29394937/array-equivalent-of-bare-string or perhaps you're asking about the application: http://stackoverflow.com/q/29848547/2642059 – Jonathan Mee Jan 18 '17 at 16:03
  • Yes, the second one *(int\* to Constant Array)* matches a part of my question. I would extend the question for non-constant arrays and for arrays of given size without specifying each item (aka. `static_new int[4]`). Since I guessed that there is no such feature yet, I further asked if some feature may be added to C++ in the future. – JojOatXGME Jan 18 '17 at 16:14
  • @JojOatXGME I think you've still got a bit of a misconception of string literals for example. I've tried to clarify my answer a bit.You bring up `constexpr` which should probably be addressed. These variables are fully initalizable at compile time, and may be used by the compiler to make decisions in optimizing and potentially pruning code braches. But even `constexpr` variables that are used at run-time will have Static or Automatic Storage Duration. – Jonathan Mee Jan 18 '17 at 16:41
  • There is some type of stoarge allocation and initialization at compile time. If you write `int x = 4;`, your compiler allocates 4 bytes in the data section and writes *4* to it. However, since `constexpr`-functions can be executed at runtime with dynamic arguments, such allocation can't work here. This means you are right that an implementation that can handle allocations in both situation is impossible. Even so, by providing an alternative keyword for `constexpr` that allows execution at compile-time only, you would bypass the problem. But I had not thought so far as I wrote the question. :/ – JojOatXGME Jan 18 '17 at 17:33
1

First of all, memory for variables with static duration is not really allocated at compile time. It is allocated at linking time or even at startup time. While the difference is subtle, it matters in some cases.

Second of all, what you are looking for seems to be a way to allocate chunks of data with automatic or static duration. Traditionally it is done with C-style arrays, std::array, and, using VLA extension when available, as VLA arrays.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • As far as I know, VLAs are not allocated at compile-time / linking time (The don't have static duration). After all, they have local scobe and can't be located in static memory since you may need more then one instance in some situations. As far as I know, they are placed on the stack. – JojOatXGME Jan 18 '17 at 16:24
0

The requested feature is partly scheduled for C++20. Only transient allocations are allowed for now.

This means new will be valid at compile time. However, the memory allocated at compile time is currently not allowed to leak into the runtime. The reasoning behind this limitation can be found in P0784. Support for non-transient allocations might be added in future versions.

JojOatXGME
  • 3,023
  • 2
  • 25
  • 41