首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++20编译时间评估、优化与指针

C++20编译时间评估、优化与指针
EN

Stack Overflow用户
提问于 2021-07-01 16:59:19
回答 1查看 154关注 0票数 2

使用std::shared_ptr不允许编译时评估、计算、内联和其他优化。这可能是由于多线程安全。

因此,我尝试了我自己的简单智能指针,只是为了看看什么是可能的,如果线程安全是不需要的。这只是一个侵扰性的、链接的列表引用跟踪智能指针的最小草案(更多信息请参见示例中的注释)。

问题:

  1. 下面的示例在clang上编译为完整的编译时间评估。关于gcc,情况并非如此。为什么?
  2. clang确实计算了所有的编译时间,如果并且只有当包含了一些空指针检查时(参见~myptr())。为什么?
  3. 由于智能指针的不变量,实际上不需要这些空指针检查。是否有一个属性等告诉clang信任指针永远不为空?

https://godbolt.org/z/1xK1r4YjT

代码语言:javascript
复制
#include <memory>
//#include <iostream>

// Simplistic linked list reference tracking smart pointer.
//
// Linking instead of reference counting is interesting because it allows for extra functionality such as
// moving around referenced memory blocks (growable objects, defragmentation), "set null" 
// semantics on delete, etc.
// 
// Not thread safe, but (trying to) support a high level of compile time evaluation, inlining, 
// optimization. 
template<typename T>
struct myptr {
private:
    T * p;
    myptr * next;
public:
    constexpr myptr(T * p) noexcept : p(p), next(p ? p->first : nullptr) {
        p->first = this;
    }
    constexpr myptr(const myptr & other) noexcept : myptr(other.p) {}

    constexpr T &operator*() {
        return *p;
    }
    constexpr T *operator->() {
        return p;
    }
    T &operator=(const myptr & other) = delete;
    T &operator=(const myptr && other) = delete;

    constexpr ~myptr() noexcept {
        if (p) {
            // We must remove `this` from the list. As these are typically stack references, they will be 
            // mostly LIFO, so we will typically find it immediately.
#if 1
            myptr ** pnext = &(p->first);
            while (*pnext) { 
                if (*pnext == this) {
                    // Found our smart pointer, bypass.
                    *pnext = next;
                    break;
                }
                pnext = &((*pnext)->next);
            }
#else
            // NOTE: the loop with null check (above) should not be necessary, as the invariant of myptr holds 
            // that we will always find `this` in the list and never hit a null pointer. 
            // However, if we use the code below, clang will immediately stop compile time evaluation. 
            // Is there some "function with potential null pointer fault" restriction in play?
            myptr ** pnext = &(p->first);
            while (*pnext != this) { 
                pnext = &((*pnext)->next);
            }
            // Bypass.
            *pnext = next;
#endif
            next = nullptr;
            if (!p->first) {
                // The last reference vanished.
                delete p;
            }
            p = nullptr;
        }
    }
};

struct Obj {
    int i{20};
    inline ~Obj() noexcept {
        i = -1;
        //std::cout << "destructor" << std::endl;
    }
private:
    // intrusive linked references list
    struct myptr<Obj> * first{};
    friend struct myptr<Obj>;
};

// Try different pointers:
using obj_ptr = myptr<Obj>;
//using obj_ptr = std::shared_ptr<Obj>;
//using obj_ptr = Obj*;

//constexpr
inline 
int fun(obj_ptr obj) {
    return obj->i;
}

int main() {
    obj_ptr obj(new Obj);
    {   obj_ptr obj2(obj);
        obj2->i += 1;
    }
    obj_ptr obj3(obj);
    obj3->i *= 2;
    return fun(obj);
}
EN

回答 1

Stack Overflow用户

发布于 2021-07-01 19:20:46

下面的示例在clang上编译为完整的编译时间评估。关于gcc,情况并非如此。为什么?

因为这两种行为都不是必需的。constexpr并不意味着“函数将在编译时执行”。这意味着编译器可以在编译时进行这样的评估.只有在必须计算为常量表达式的上下文中调用该函数时,才需要该函数。

你在这里可不是这么做的。

您在Clang上看到的优化与constexpr限定符无关。把那些限定符拿走,然后Clang仍在优化它。它们只是常规的编译器优化。

clang确实计算了所有的编译时间,如果并且只有当包含了一些空指针检查(请参见~myptr())时。为什么?

编译器优化是挑剔的,有时非常武断。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68214215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档