вторник, 4 апреля 2023 г.

[prog.c++] Две отличные статьи про неочевидные моменты C++

Две небольшие, но отличные статьи на сайте devblogs.microsoft.com: "C++17 creates a practical use of the backward array index operator" и "The mystery of the crash that seems to be on a std::move operation". Они, хоть и на английском, но читаются легко. Да и самое главное там -- это примеры. Посему решил сохранить их в склерознике :)

Позволю себе процитировать оттуда пару-тройку фрагментов.

Из первой статьи:

Another practical use is to bypass any possible overloading of the [] operator, as noted in Chapter 14 of Imperfect C++:

#define ARRAYSIZE(a) (sizeof(a) / sizeof(0[a]))

By flipping the order in 0[a], this bypasses any possible a[] overloaded.

std::vector<int> v(5);
int size = ARRAYSIZE(v); // compiler error

However, it isn’t foolproof. You just need to create a more clever fool: If v is a pointer or an object convertible to a pointer, then that pointer will happily go inside the 0[...].

struct Funny
{
    operator int*() { return oops; }
    int oops[5];
    int extra;
};

Funny f;
int size1 = ARRAYSIZE(f); // oops: 6

int* p = f;
int size2 = ARRAYSIZE(p); // oops: 1

Из второй статьи.

Вот этот код на ARM-е ломается при компиляции в режиме C++14:

void polarity_test(std::shared_ptr<Test> test)
{
    test->harness->callAndReport([test2 = std::move(test)]() mutable
    {
        test2->reverse_polarity();
        ::resume_on_main_thread([test3 = std::move(test2)]()
        {
            test3->reverse_polarity();
        });
    });
}

Ломается потому, что вот здесь:

test->harness->callAndReport([test2 = std::move(test)]() mutable

значение test может быть перестать актуальным еще до того, как произойдет обращение к test->harness.

Но, начиная с C++17 это уже не проблема.

Комментариев нет: