#include <vector> #include <array> #include <iostream> using PointType = std::array<double,3>; class Point : public PointType { public: using PointType::PointType; Point(const Point& copy) : PointType(copy) { std::cout << "Point(const Point&)" << std::endl; } Point(Point&& rval) : PointType(rval) { std::cout << "Point(Point&&)" << std::endl; } // Prevent polygonType* p = new polygon; delete p; template<typename ...Args> void* operator new (size_t,Args...) = delete; }; using polygonType = std::vector<PointType>; class polygon : public polygonType { public: using polygonType::polygonType; polygon(const polygon& copy) : polygonType(copy) { std::cout << "polygon(const polygon&)" << std::endl; } polygon(polygon&& rval) : polygonType(rval) { std::cout << "polygon(polygon&&)" << std::endl; } // Prevent polygonType* p = new polygon; delete p; template<typename ...Args> void* operator new (size_t,Args...) = delete; };
如果我对从未使用Point或polygon或类似类型的new感到满意,删除new运算符会解决未定义行为的问题:
std::array<double,3> a = new Point({1.,2.,3.}) delete a;
std :: vector< PointType>上的条件由对其起作用的算法强加的算法是:算法检查公共接口是否适合算法中的操作.如果我想要一个算法(函数模板)来查看这个点向量作为线段的开链或闭合多边形,这是一个问题.这解析了在解析函数模板候选时依赖于隐式接口.此外,概念在它们到达时对我没有帮助,因为同样,容器上的条件是相同的,我希望算法对它们做的不同.因此,如果我执行标记调度with SFINAE using the new metafunctions from type_traits
以检查模板参数是否已使用特定标记进行标记,那么使用这样的具体类型并标记它们会使标记调度变得微不足道.
解决方法
从标准容器中获取并非完全禁止,这只是危险的.通过消除危险的用例,您似乎在很大程度上减轻了危险.
请注意,如果您确实允许动态分配然后通过指向基类的删除,即使派生类没有自己的状态(即没有成员),您仍然有UB.对象生命周期比仅计算数据成员要复杂得多.
您仍然可以允许动态分配,并且永远不会通过指向基础的指针进行删除,但是这在逻辑上是否适合您,更不用说足够的保护性,仅取决于上下文.
轶事:我偶尔会从“图书馆代码”中的矢量/地图继承而不打算被其他任何人进一步扩展.它不是开源软件,它是我控制下的专有代码库,因此自由使用评论很好.如果要通过容器的整个界面,组合会有点痛苦.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。