Practicing RAII

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <functional>
#include <new>
#include <random>
#include <algorithm>

struct AutoRAII
{
    using Func = std::function<void()>;
    AutoRAII(Func const&init, Func const&rel) : rel(rel)
    {
        init();
    }
    ~AutoRAII()
    {
        rel();
    }
private:
    Func const&rel;

    AutoRAII() = delete;
    AutoRAII(AutoRAII const&) = delete;
    AutoRAII(AutoRAII &&) = delete;
    AutoRAII &operator=(AutoRAII const&) = delete;
    AutoRAII &operator=(AutoRAII &&) = delete;
    void *operator new(std::size_t, ...) = delete;
    void operator delete(void *) = delete;
    void operator delete[](void *) = delete;
};

int main()
{
    using example_t = std::mt19937_64::result_type;
    example_t *example {nullptr};
    std::size_t const len {4};
    AutoRAII print
    {
        [&example, &len]
        {
            example = new example_t[len];
            std::mt19937_64 mt {};
            std::for_each(example, example+len,
            [&mt](example_t &i)
            {
                i = mt();
            });
            std::cout << "Initialize" << std::endl;
        },
        [&example]
        {
            std::cout << "Release" << std::endl;
            delete[] example, example = nullptr;
        }
    };
    std::for_each(example, example+len,
    [](example_t &i)
    {
        std::cout << i << std::endl;
    });
}
Initialize
14514284786278117030
4620546740167642908
13109570281517897720
17462938647148434322
Release

http://liveworkspace.org/code/tNSjI$21
How should I improve this?
Last edited on
If allocated with new[] you must deallocate with delete[]

Don't sure what you are trying to show.
Haha, whoops - it's been ages since I did manual memory management. Fixed.

I'm trying to show the AutoRAII class.
Last edited on
Yes, but I only see a c++ wrapper for c OOP, and unneeded dynamic allocation.
Most of this is opinion so take it for what it's worth. But that is kind of what you asked for...

1) You're over-reaching to apply some C++11 features. Specifically lambdas and foreach. In effect you're just obfuscating the code.

1
2
3
4
5
6
7
8
9
10
11
12
// compare:
    std::for_each(example, example+len,
    [](example_t &i)
    {
        std::cout << i << std::endl;
    });

// vs:
    for(int i = 0; i < len; ++i)
    {
        std::cout << example[i] << std::endl;
    }



2) Why are you bothering to delete new/delete operators for the RAII class? How would that be of any benefit?


3) wtf @ the comma operator usage on line 52.
1. In a lot of the code I work with the std::for_each+lambda version is much easier to read, it's just force of habit.
2. I called it "example" for a reason; pretend it is something for which there is not already an RAII wrapper.
3. It ensures that no code gets put between the invalidation of the pointer and the nullification of the pointer, also a force of habit.
3) wtf @ the comma operator usage on line 52.
I've seen it done several times in C++11 code.
But do I have the rough concept of RAII down? The RAII class is supposed to be used when there doesn't already exist an RAII wrapper for something that can be constructed and destructed. Am I even on the right track?
I guess. I think that in the best case though you would just modify the class/object itself to have a proper constructor/destructor. Maybe you could use for a custom setup/desetup for something though, but in that case I'd probably just make another class that did it in its constructor/desctructor instead.
Topic archived. No new replies allowed.