Chr*_* A. 2 c++ copy-constructor visual-studio-debugging return-value-optimization
我最近遇到的最有趣的C++问题如下:
我们确定(通过分析)我们的算法在MS Visual Studio 2005中的调试模式中花费了大量时间,具有以下类型的函数:
MyClass f(void)
{
MyClass retval;
// some computation to populate retval
return retval;
}
Run Code Online (Sandbox Code Playgroud)
正如你们大多数人可能知道的那样,这里的返回调用一个拷贝构造函数来传递一个副本,retval然后传递析构函数retval.(注意:原因释放模式非常快,因为返回值优化.但是,我们希望在调试时关闭它,以便我们可以介入并很好地查看调试器IDE中的内容.)
所以,我们的一个人提出了一个很酷的(如果有点缺陷)解决方案,这就是创建转换运算符:
MyClass::MyClass(MyClass *t)
{
// construct "*this" by transferring the contents of *t to *this
// the code goes something like this
this->m_dataPtr = t->m_dataPtr;
// then clear the pointer in *t so that its destruction still works
// but becomes 'trivial'
t->m_dataPtr = 0;
}
Run Code Online (Sandbox Code Playgroud)
并将上述功能更改为:
MyClass f(void)
{
MyClass retval;
// some computation to populate retval
// note the ampersand here which calls the conversion operator just defined
return &retval;
}
Run Code Online (Sandbox Code Playgroud)
现在,在你畏缩之前(我正在写这篇文章),让我解释一下这个理由.我们的想法是创建一个转换运算符,它基本上将"内容传输"转换为新构造的变量.节省的原因是因为我们不再进行深层复制,而只是通过指针传输内存.代码从10分钟的调试时间到30秒的调试时间,您可以想象,这对生产力有巨大的积极影响.当然,返回值优化在发布模式下做得更好,但代价是无法介入并观察我们的变量.
当然,大多数人会说"但这是滥用转换操作符,你不应该做这种事情",我完全同意.这是一个为什么你不应该这样做的例子(这实际上发生了:)
void BigFunction(void)
{
MyClass *SomeInstance = new MyClass;
// populate SomeInstance somehow
g(SomeInstance);
// some code that uses SomeInstance later
...
}
Run Code Online (Sandbox Code Playgroud)
其中g定义为:
void g(MyClass &m)
{
// irrelevant what happens here.
}
Run Code Online (Sandbox Code Playgroud)
现在这是偶然发生的,即,g()当预期引用时,调用的人不应该传入指针.但是,没有编译器警告(当然).编译器确切知道如何转换,它就是这样做的.问题是对g()will 的调用(因为我们MyClass *在它预期时已经传递了它MyClass &)调用了转换运算符,这很糟糕,因为它将内部指针设置SomeInstance为0,并且SomeInstance对于之后发生的代码无效打电话给g()....随后进行了耗时的调试.
所以,我的问题是,我们如何在调试模式下获得这种加速(具有直接调试时间的好处),干净的代码无法打开使这些其他可怕错误滑过裂缝的可能性?
我也将在这个上加油,并且一旦它符合条件,就会在这个上提供我的第一笔赏金.(50分)
您需要使用称为"交换优化"的东西.
MyClass f(void)
{
MyClass retval;
// some computation to populate retval
return retval;
}
int main() {
MyClass ret;
f().swap(ret);
}
Run Code Online (Sandbox Code Playgroud)
这将防止复制并在所有模式下保持代码清洁.
你也可以尝试相同的技巧auto_ptr,但这不仅仅是一点点.
| 归档时间: |
|
| 查看次数: |
564 次 |
| 最近记录: |