这里有一个粗心写的模板,有些过分内联 - 在C++中编写膨胀代码太容易了.原则上,重构以减少膨胀不是太难.问题在于跟踪最严重的违规模板和内联 - 跟踪那些在真实程序中导致真正膨胀的项目.
考虑到这一点,并且因为我确信我的库比他们应该更容易臃肿,我想知道是否有任何工具可以自动追踪那些最严重的违规者 - 即识别那些贡献最多的项目(包括所有重复的实例化和调用)到特定目标的大小.
此时我对性能不太感兴趣 - 这完全取决于可执行文件的大小.
有没有这个工作的工具,可以在Windows上使用,并适合MinGW GCC或Visual Studio?
编辑 - 一些背景
我有一组多路树模板,可以替代红黑树标准容器.它们是围绕非类型安全的非模板代码编写的,但它们也是很久以前编写的,并且作为"将更好地缓存友好性提升实际性能"实验.关键是,它们并非真正用于长期使用.
因为它们支持一些方便的技巧(基于自定义比较/部分键搜索,有效的下载访问,搜索最小的未使用的键),它们最终在我的代码中的任何地方都被使用.这些天,我几乎没有使用std :: map.
除了那些之外,我还有一些更复杂的容器,比如双向地图.最重要的是,我有树和有向图类.除此之外......
使用地图文件,我可以追踪非内联模板方法是否导致膨胀.这只是找到特定方法的所有实例并添加大小的问题.但是不明智的内联方法呢?毕竟,模板是非模板代码的薄包装,但历史上我判断是否应该内联的能力并不是非常可靠.这些模板内联的膨胀影响并不容易衡量.
我知道哪些方法被大量使用,但这是众所周知的opimization-without-profiling错误.
我一直在寻找,但似乎编译器开发人员对支持这些没有兴趣.
对我来说,这看起来很奇怪 - 基本上,目前的C++对工会有一些限制,这些工会总是令人不快,而且永远不合适.您认为基本上删除一些错误检查将是一个相对简单的方法来勾选额外的c ++ 0x支持框,但AFAICT没有编译器开发人员已经这样做了.
为什么我感兴趣是因为它为数据结构编码中反复出现的问题提供了一个简单的解决方案 - 如何为某个未知(模板参数)类型的实例保留内存,最好在这种情况下尽可能多地保证类型安全,但是不调用恰好在该类型上定义的任何构造函数.非常重要的一点是必须遵循对齐规则.
一个不受限制的联合是完美的 - 它给你一种没有构造函数或析构函数的类型,但它具有正确的大小和对齐以允许任何成员.当然有需要在需要时显式构造和销毁的方法,当您需要类型安全访问时,您只需使用适当的union成员来访问它.对"正确"工会的支持也很有用,但即使对于单一成员工会,您也可以获得巨大的利益,例如...
union Memory_For_Item_t
{
Item_t m_Item;
};
Run Code Online (Sandbox Code Playgroud)
即使使用C++ 0x中的标准化对齐处理功能,这种方法也可以获得方便性和安全性,例如,您需要节点中x项的空间,而不是所有这些项都可以随时使用(或构建).如果没有C++ 0x,我们仍处于黑暗时代的WRT对齐问题 - 每个编译器都以自己的非标准方式进行.
无限制工会的唯一问题 - 我找不到对他们的支持.
偶尔,我会注意到我已经使用多年的编码模式,这让我很紧张.我没有具体的问题,但我也不记得为什么我采用了这种模式,并且它的某些方面似乎与某些反模式匹配.这最近发生在WRT我的一些代码如何使用异常.
令人担忧的事情涉及我通过"引用"捕获异常的情况,以类似于我将参数处理为函数的方式处理它.这样做的一个原因是我可以拥有异常类的继承层次结构,并根据应用程序指定更通用或更精确的捕获类型.例如,我可能会定义......
class widget_error {};
class widget_error_all_wibbly : public widget_error {};
class widget_error_all_wobbly : public widget_error {};
void wibbly_widget ()
{
throw widget_error_all_wibbly ();
}
void wobbly_widget ()
{
throw widget_error_all_wobbly ();
}
void call_unknown_widget (void (*p_widget) ())
{
try
{
p_widget ();
}
catch (const widget_error &p_exception)
{
// Catches either widget_error_all_wibbly or
// widget_error_all_wobbly, or a plain widget_error if that
// is ever thrown by anything.
}
}
Run Code Online (Sandbox Code Playgroud)
现在这让我很担心,因为我注意到在一个函数中构造了一个类实例(作为throw的一部分),但是在该函数退出之后被引用(通过p_Exception catch-clause"参数").这通常是一个反模式 - 一个局部变量的引用或指针或在函数内创建的临时变量,但在函数退出时传递出来,通常是一个悬空引用/指针,因为局部变量/ temporary被破坏并且内存被释放当函数退出时.
一些快速测试表明上面的抛出可能没问题 - 当函数退出时,throw子句中构造的实例不会被破坏,但是当处理它的catch子句完成时会被破坏 - 除非catch块重新抛出异常,在哪种情况下,下一个捕获块完成这项工作. …
一次比较每次迭代二进制搜索有什么意义?你能解释它是如何工作的吗?
我想通过智能指针引用将对象传递给函数.该函数可能会更改引用对象的值,但可能不会更改引用本身.有两种明显的方法可以解决这个问题.
第一种通过值传递shared_ptr的方法 - 它是引用,因此本身不需要通过引用传递.这个问题的明显问题是复制引用,这表明一些引用计数开销.
void foo (shared_ptr<bar> p)
Run Code Online (Sandbox Code Playgroud)
第二种方法是通过const引用传递shared_ptr - 避免复制shared_ptr实例,而是暗示对引用对象的访问需要两层解除引用而不是一层.
void foo (const shared_ptr<bar> &p)
Run Code Online (Sandbox Code Playgroud)
在实践中,这些理论上的开销通常是微不足道的,无关紧要的.这告诉我,我不应该为每个案例选择一种方法,而应该遵循一些标准惯例.这导致了这个问题......
我通常应该选择哪种方法的标准惯例?如果是这样,这是传统的选择吗?
编辑 - 可能值得一提 - 考虑const-by-const-reference案例的一个原因是因为有一个预先存在的约定,大多数类/结构实例是由const-reference而不是value传递的,并且shared_ptr是一个类.当然它不是重量级的(复制成本很小),因此旧约定背后的原因可能不适用.
我不确定我是否因为文档错误或头痛而遭受更多痛苦,所以...
我想要做的是创建一个shared_ptr,它与另一个共享所有权,但引用对象的成员而不是整个对象.简单的例子,起点......
struct s
{
int a, b;
};
shared_ptr<s> s1 (new s); // pointing to whole object
Run Code Online (Sandbox Code Playgroud)
从en.cppreference.com,shared_ptr的构造函数(8)是......
template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );
Run Code Online (Sandbox Code Playgroud)
该描述提到"构造一个shared_ptr,它与r共享所有权信息,但是保存一个不相关且不受管理的指针ptr ......例如在ptr是由r管理的对象的成员的典型用例中".
所以... T只是意外地错过了那个构造函数中的模板,或者我错过了什么?事实上,Y看起来对我来说也是错的,所以通常只是构造函数描述正确吗?
我希望我能做的就是这样......
shared_ptr<int> s2 (s1, &(s1.get ()->a));
Run Code Online (Sandbox Code Playgroud)
s2指向成员a(an int),但与...共享整个对象的所有权s1.
这样理智吗?
作为一个基本的Prolog练习,我自己设定了编写二进制树高度谓词的任务,该谓词可以向前和向后工作 - 也就是说,除了确定已知二叉树的高度之外,它应该能够找到所有二进制已知高度的树木(包括不平衡的树木).这是我到目前为止提出的最佳解决方案......
tree_eq1([],s). % Previously had a cut here - removed (see comments for reason)
tree_eq1([_|T],n(L,R)) :- tree_eq1(T,L), tree_eq1(T,R).
tree_eq1([_|T],n(L,R)) :- tree_eq1(T,L), tree_lt1(T,R).
tree_eq1([_|T],n(L,R)) :- tree_lt1(T,L), tree_eq1(T,R).
tree_lt1([_|_],s).
tree_lt1([_,X|T],n(L,R)) :- XX=[X|T], tree_lt1(XX,L), tree_lt1(XX,R).
Run Code Online (Sandbox Code Playgroud)
第一个参数是高度,表示为列表 - 元素无关,列表的长度表示树的高度.所以我基本上滥用列表作为Peano风格的自然数字.这很方便的原因是......
这些属性似乎都不适用于Prolog数字,到目前为止我无法想到采用相同的基本方法来使用实际数字来代替这些列表.
我在Prolog中看到了一些使用Peano风格数字的例子,所以我的问题是 - 这是正常的做法吗?还是有办法避免我还没有发现的问题?
此外,有没有办法转换为Peano风格的表示,从而不会破坏双向性?以下因为相当明显的原因不起作用......
length(L,N), tree_eq1(L,X).
% infinite set of lists to explore if N is unknown
tree_eq1(L,X), length(L,N)
% infinite set of trees to explore if X is unknown
Run Code Online (Sandbox Code Playgroud)
到目前为止,我能想到的最好的是一个is-this-variable-instantiated test,可以在实现之间进行选择,这对我来说就像是在欺骗.
BTW - 我对其他方法有一些想法,我不想要剧透 …
我现在正在写一个非常复杂和狡猾的游戏,这会让你充满敬畏和喜悦 - 哦,好吧,这是15个谜题,我只是熟悉SDL.
我正在窗口模式下运行,并使用SDL_Flip作为一般情况页面更新,因为它在窗口模式下自动映射到完整窗口的SDL_UpdateRect.不是最佳方法,但鉴于这只是15个难题......
无论如何,瓷砖移动的速度很快.IOW,窗口模式下的SDL_Flip不包括与垂直回扫的任何同步.我在Windows XP ATM中工作,但我认为这是SDL的正确行为,也会在其他平台上发生.
切换到使用SDL_UpdateRect显然不会改变任何东西.据推测,我需要在自己的代码中实现延迟逻辑.但是一个简单的基于时钟的计时器可能会导致窗口被半绘时发生更新,导致可见的扭曲(我忘记了技术名称).
编辑 这个问题被称为"撕裂".
那么 - 在SDL的窗口模式游戏中,如何将页面翻转与垂直回扫同步?
编辑 我在搜索解决方案时看到了几个声明,在窗口化的应用程序中无法将页面翻转同步到垂直回扫.在Windows上,至少,这简直是假的 - 我写过游戏(我的意思是与15拼图类似的东西).我曾经浪费过一段时间玩Dark Basic和Dark GDK--基于DirectX和同步翻页都是在窗口模式下垂直回扫.
在过去的几个月里,我一直在努力学习Haskell - 之前,我是一个看似永恒的新手,对基础知识知之甚少.在试图将我的新知识付诸实践时,我将继续发现我希望使用基于类型类的类似代理的模式.前两次,当我弄清楚它为什么不起作用时,我认为它"好吧 - 我可能找不到一个惯用的Haskell替代品,但问题是这里的问题是我使用了错误的方法语言".但是,我发现的是,我真的真的不喜欢不能够做代理状的东西.
为了更深入地理解为什么我不能使用代理,经过大量的实验,我终于想出了GHC更高级别的类型扩展,也许我可以有代理.但我仍然无法使其发挥作用,我不确定为什么.
这是我管理过的最好的代码......
{-# LANGUAGE RankNTypes #-}
module Test where
-- Simple type class based on parser combinators.
class Gen g where
get :: g x -> [(x, g x)]
instance Gen [] where
get [] = []
get (x:xs) = [(x, xs)]
-- Proxy type - holds a pair containing...
-- - a value of some type that supports Gen
-- - a function to indicate when an item should be skipped
newtype …Run Code Online (Sandbox Code Playgroud) 这个问题和我下面的答案主要是为了回应另一个问题中的一个混乱领域.
在答案的最后,有一些问题WRT"易变"和线程同步,我不是完全有信心 - 我欢迎评论和替代答案.然而,问题的关键主要涉及CPU寄存器及其使用方式.
compiler-construction assembly code-generation cpu-registers