Home > Back-end >  C constructor on unnamed object idiom?
C constructor on unnamed object idiom?

Time:10-06

I have a C class that works like the Linux "devmem" utility for embedded systems. I'll simplify and give an outline of it here:

struct DevMem
{
    DevMem(off_t start, off_t end)
    {
        // map addresses start to end into memory with mmap
    }

    ~DevMem()
    {
        // release mapped memory with munmap
    }

    uint32_t read(off_t address)
    {
        // return the value at mapped address
    }

    void write(off_t address, uint32_t value)
    {
        // write value to mapped address
    }
};

I use it like this:

void WriteConverter(uint32_t value)
{
    off_t base = 0xa0000000;
    DevMem dm(base, base 0x100);  // set up mapping for region

    dm.write(base 0x8, value);    // output value to converter
    dm.write(base 0x0, 1);        // strobe hardware
    while (dm.read(base 0x4))     // wait until done
        ;
}

And this works great. RAII ensures the mapped memory is released when I'm done with it. But some hardware is really simple and only needs a single read or write. It was bothering me that in order to access that hardware, I would have to invent some name for the instantiation of the class:

DevMem whatever(0xa0001000, 0xa0001000);  // map the thing
whatever.write(0xa0001000, 42);           // do the thing

With the named object and the repetition of the address three times, it's a little verbose. So I made a change to the constructor so that I could leave off the end parameter if I'm only mapping a single address:

    DevMem(off_t start, off_t end = 0)
    {
        // map addresses start to end into memory with mmap
    }

And then I overloaded the read and write routines so the address wasn't passed:

    uint32_t read()
    {
        // return the value at the constructor's start address
    }

    void write(uint32_t value)
    {
        // write value to the constructor's start address
    }

And I discovered that I could then do this:

DevMem(0xa0001000).write(42);    // do the thing

And this works. I don't need to invent a name for the object, it's less verbose, the value is written (or read), and RAII cleans it up nicely. What I assume is happening is that C is constructing an unnamed object, dereferencing it, using it, and then destructing it.

Is this use of an unnamed object valid? I mean, it compiles okay, GCC and clang don't complain with common warnings cranked up, and it does actually work on the target hardware. I just can't find any examples of such a thing on the Interwebs. Is this a named idiom?

CodePudding user response:

Yep, completely valid. You create the object, use it and then the destructor kicks in. Your compiler will probably generate the same assembly in your whatever example if whateverhas a reasonable scope.

I don't know any names for this construct though. As well as I wouldn't call this an idiom.

  • Related