We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
先说解决方法, 需求后面再说. 构造函数可以有自定义的, 析构函数只有一个. 而且不能直接获取构造/析构函数的指针.
其中C++允许调用其析构函数, 可参考calling destructor explicitly和Destructors (C++). 所以这样就可能间接获取析构函数的函数地址了(T是模板):
// release the object void delete_obj(void*p) noexcept { static_cast<T*>(p)->T::~T(); }
那么构造函数呢, 当然也可以直接调用, 不过这不是标准行为:
对于不允许的我们可以使用c++ placement new, 不过由于直接调用构造函数这个功能实在太诱惑了(placement new同delete一样会判断this指针, 从而间接增加代码大小, 这个由于是模板, 可不能忽略), 所以大致这么实现:
// create the object static void create_obj(void* ptr) noexcept { #ifdef CANNOT_CALL_CONSTRUCTOR_DIRECTLY // gcc cannot call ctor directly new(ptr) T(); #else // msc/clang extended support static_cast<T*>(ptr)->T::T(); #endif }
CANNOT_CALL_CONSTRUCTOR_DIRECTLY判断不是msvc或者clang但是定义了ms兼容扩展就可以取消定义.
对于自定义的(包括复制移动)构造函数就可以用c++11带来的完美转发:
// create template<typename ...Args> static void create(void* ptr, Args&&... args) noexcept { #ifdef CANNOT_CALL_CONSTRUCTOR_DIRECTLY // gcc cannot call ctor directly new(ptr) T(std::forward<Args>(args)...); #else // msc/clang extended support static_cast<T*>(ptr)->T::T(std::forward<Args>(args)...); #endif }
这样当然只是意思到了而已, 实际上会报错, 因为T是一个typename而不是一条函数(但是~T就是一条函数了, 神奇的C++或者说微软), 直接调用T::T会提示错误, 直接的解决方法当然是直接全部使用placement new, 但是我实在不想舍弃, 就再用了一层中转...
// func-vtable getter template<typename T> struct ctor_dtor { // member T m; // ctor ctor_dtor() noexcept {}; };
这样ctor_dtor<T>::ctor_dtor 就是一条函数了
ctor_dtor<T>::ctor_dtor
这样的话, 针对一些没有析构函数的对象会生成一堆没用的代码. 这个问题各大编译器厂商都有类似于ICF(等价代码折叠)的技术, 能够在链接时折叠相同的只读常量(包括函数), 不过细节不同. 对于取地址操作的函数, GCC流 会持保留态度, 也就是说这种情况ICF在GCC没用. 这种情况只能祭出神器<type_traits>了:
#include <type_traits> #include <string> #include <cstdio> #include <cstdint> template<typename T> bool get_td_lambda(T&&) noexcept { return std::is_trivially_destructible<T>::value; } int main(){ std::string aa = "asd"; const auto bool0 = get_td_lambda([]() {}); const auto bool1 = get_td_lambda([aa]() {}); const auto bool2 = get_td_lambda([&aa]() {}); std::printf("%d, %d, %d\n", int(bool0), int(bool1), int(bool2)); }
GCC/MSC 当然都是输出"1, 0, 1", 现在对于空析构函数就可以重定向到同一条了. 不过当然还是没有完美解决, 比如 [aa]() {} 这类的有N个, 虽然都是析构一个std::string但是毕竟lambda不同, gcc还是不能折叠, 如果各位有解决方法的话请回复吧.
[aa]() {}
目前LongUI大致有两种方法:
std::function
第一个就懒得说了. 说说第二个, 滥用模板的话会造成模板膨胀这是自然的, 所以为了轻量化, LongUI实现了一个不会模板膨胀的Vector(但是目前还没用过, 所以暂时被冷藏了) 内部使用的是类似虚表的实现, 所以如果保存的是轻量级对象, 比如说是智能指针这种重点是RAII的, 添加删除的效率将会比较低, 主要体现在:
当然这是轻量级的影响比较大, 重量级比如std::string重点是保存的数据这类, 基本没有太大影响. 当然由于LongUI目前使用的全是POD::Vector, 不用调用构造/析构. 这个类还没用过Orz
The text was updated successfully, but these errors were encountered:
dustpg
No branches or pull requests
解决方法
先说解决方法, 需求后面再说. 构造函数可以有自定义的, 析构函数只有一个. 而且不能直接获取构造/析构函数的指针.
其中C++允许调用其析构函数, 可参考calling destructor explicitly和Destructors (C++).
所以这样就可能间接获取析构函数的函数地址了(T是模板):
那么构造函数呢, 当然也可以直接调用, 不过这不是标准行为:
对于不允许的我们可以使用c++ placement new, 不过由于直接调用构造函数这个功能实在太诱惑了(placement new同delete一样会判断this指针, 从而间接增加代码大小, 这个由于是模板, 可不能忽略), 所以大致这么实现:
CANNOT_CALL_CONSTRUCTOR_DIRECTLY判断不是msvc或者clang但是定义了ms兼容扩展就可以取消定义.
对于自定义的(包括复制移动)构造函数就可以用c++11带来的完美转发:
错误处理
这样当然只是意思到了而已, 实际上会报错, 因为T是一个typename而不是一条函数(但是~T就是一条函数了, 神奇的C++或者说微软), 直接调用T::T会提示错误, 直接的解决方法当然是直接全部使用placement new, 但是我实在不想舍弃, 就再用了一层中转...
这样
ctor_dtor<T>::ctor_dtor
就是一条函数了代码优化
这样的话, 针对一些没有析构函数的对象会生成一堆没用的代码. 这个问题各大编译器厂商都有类似于ICF(等价代码折叠)的技术, 能够在链接时折叠相同的只读常量(包括函数), 不过细节不同. 对于取地址操作的函数, GCC流 会持保留态度, 也就是说这种情况ICF在GCC没用.
这种情况只能祭出神器<type_traits>了:
GCC/MSC 当然都是输出"1, 0, 1", 现在对于空析构函数就可以重定向到同一条了. 不过当然还是没有完美解决, 比如
[aa]() {}
这类的有N个, 虽然都是析构一个std::string但是毕竟lambda不同, gcc还是不能折叠, 如果各位有解决方法的话请回复吧.应用场景
目前LongUI大致有两种方法:
std::function
第一个就懒得说了. 说说第二个, 滥用模板的话会造成模板膨胀这是自然的, 所以为了轻量化, LongUI实现了一个不会模板膨胀的Vector(但是目前还没用过, 所以暂时被冷藏了)
内部使用的是类似虚表的实现, 所以如果保存的是轻量级对象, 比如说是智能指针这种重点是RAII的, 添加删除的效率将会比较低, 主要体现在:
当然这是轻量级的影响比较大, 重量级比如std::string重点是保存的数据这类, 基本没有太大影响. 当然由于LongUI目前使用的全是POD::Vector, 不用调用构造/析构. 这个类还没用过Orz
The text was updated successfully, but these errors were encountered: