我在一个类中有一个函数,我希望编译器在......一直使用 NRVO......即使在调试模式下也是如此。对此有语用吗?
这是我的课程在“发布”模式下效果很好:
template <int _cbStack> class CBuffer {
public:
CBuffer(int cb) : m_p(0) {
m_p = (cb > _cbStack) ? (char*)malloc(cb) : m_pBuf;
}
template <typename T> operator T () const {
return static_cast<T>(m_p);
}
~CBuffer() {
if (m_p && m_p != m_pBuf)
free(m_p);
}
private:
char *m_p, m_pBuf[_cbStack];
};
除非需要超过 _cbStack 字节,否则该类用于在堆栈上创建缓冲区。然后当它销毁时,如果它分配了任何内存,它就会释放内存。当与需要字符串缓冲区的 c 函数交互时,它很方便,并且您不确定最大大小。
无论如何,我试图编写一个可以返回 CBuffer 的函数,就像在这个测试中一样:
#include "stdafx.h"
#include <malloc.h>
#include <string.h>
template <int _cbStack> CBuffer<_cbStack> foo()
{
// return a Buf populated with something...
unsigned long cch = 500;
CBuffer<_cbStack> Buf(cch + 1);
memset(Buf, 'a', cch);
((char*)Buf)[cch] = 0;
return Buf;
}
int _tmain(int argc, _TCHAR* argv[])
{
auto Buf = foo<256>();
return 0;
}
我指望 NRVO 让 foo() 快速。在发布模式下,它工作得很好。在调试模式下,它显然会失败,因为我的类中没有复制构造函数。我不想要复制构造函数,因为喜欢复制所有内容 50 次的开发人员将使用 CBuffer。(咆哮:这些家伙正在使用动态数组类创建一个包含 20 个字符的缓冲区以传递给 WideCharToMultiByte(),因为他们似乎忘记了您可以只在堆栈上分配一个字符数组。我不知道是否他们甚至知道堆栈是什么......)
我真的不想编写复制构造函数,以便代码在调试模式下工作!它变得庞大而复杂:
template <int _cbStack>
class CBuffer {
public:
CBuffer(int cb) : m_p(0) { Allocate(cb); }
CBuffer(CBuffer<_cbStack> &r) {
int cb = (r.m_p == r.m_pBuf) ? _cbStack : ((int*)r.m_p)[-1];
Allocate(cb);
memcpy(m_p, r.m_p, cb);
}
CBuffer(CBuffer<_cbStack> &&r) {
if (r.m_p == r.m_pBuf) {
m_p = m_pBuf;
memcpy(m_p, r.m_p, _cbStack);
} else {
m_p = r.m_p;
r.m_p = NULL;
}
}
template <typename T> operator T () const {
return static_cast<T>(m_p);
}
~CBuffer() {
if (m_p && m_p != m_pBuf)
free((int*)m_p - 1);
}
protected:
void Allocate(int cb) {
if (cb > _cbStack) {
m_p = (char*)malloc(cb + sizeof(int));
*(int*)m_p = cb;
m_p += sizeof(int);
} else {
m_p = m_pBuf;
}
}
char *m_p, m_pBuf[_cbStack];
};
此编译指示不起作用:
#pragma optimize("gf", on)
有任何想法吗?