在问题叙述之前,我们先来看一段代码。
class MyString
{
public:
char* GetBuffer() const
{
return m_pBuffer;
}
private:
void CopyContent(const char* pSrc)
{
m_pBuffer = new char [strlen(pSrc) + 1];
strcpy(m_pBuffer,pSrc);
}
public:
MyString() : m_pBuffer(0)
{
}
MyString(const char* pSrc) : m_pBuffer(0)
{
CopyContent(pSrc);
}
MyString(const MyString& src) : m_pBuffer(0)
{
char* p = src.GetBuffer();
CopyContent(p);
}
~MyString()
{
if(m_pBuffer)
{
delete [] m_pBuffer;
}
}
public:
MyString& operator = (const MyString& src)
{
if(this != &src)
{
char* newdata = new char[strlen(src.GetBuffer()) + 1];
if(m_pBuffer)
delete [] m_pBuffer;
m_pBuffer = newdata;
}
strcpy(m_pBuffer,src.GetBuffer());
return *this;
}
MyString& operator += (const MyString& src)
{
size_t newsize = 0;
newsize = strlen(m_pBuffer) + strlen(src.GetBuffer()) + 1;
char* newdata = new char[newsize];
strcpy(newdata,m_pBuffer);
strcat(newdata,src.GetBuffer());
delete [] m_pBuffer;
m_pBuffer = newdata;
return *this;
}
MyString& operator += (const char* src)
{
size_t newsize = 0;
newsize = strlen(m_pBuffer) + strlen(src) + 1;
char* newdata = new char[newsize];
strcpy(newdata,m_pBuffer);
strcat(newdata,src);
delete [] m_pBuffer;
m_pBuffer = newdata;
return *this;
}
friend MyString operator + (const MyString& src1, const MyString& src2)
{
MyString res = src1;
res += src2;
return res;
}
friend MyString operator + (const char* src1, const MyString& src2)
{
MyString res = src1;
res += src2;
return res;
}
friend MyString operator + (const MyString& src1, const char* src2)
{
MyString res = src1;
res += src2;
return res;
}
operator char* ()
{
return GetBuffer();
}
private:
char* m_pBuffer;
};
int _tmain(int argc, _TCHAR* argv[])
{
MyString a("abc");
MyString b("def");
MyString T = a + b; //方法1
MyString K;
K = a + b; //方法2
//方法1,方法2那个更有效率呢?
char* pTemp = 0;
pTemp = (char*)(MyString("123") + MyString("456"));
//....
//访问pTemp,怎么有地址,却没有内容呢?
return 0;
}
大家可以单步调试一下,你就会发现一些有趣的现象。原来这一切都是编译器在搞的鬼。
在写C++代码时,关于临时对象的问题,有几点是必须要注意的。
1 C++标准允许编译器来定义临时对象。对于大多数流行的编译器来说,
如果有下列的表达式:
T a, b;
T c = a + b; (1)
而其中的加法定义为:
T operator + (const T&, const T &);
那么1 式实现就不会有临时对象的产生。
然而 ,意义相等的赋值语句,就不能够忽略临时对象的产生,这点可以从上面的代码中得以验证。
T c;
c = a + b;
展开成C++伪代码是:
///
T temp;
temp.operator + (a, b);
c.operator = (temp);
temp.T::~T();
2 临时对象的被摧毁,应该是对完整表达式求值过程中最后一个步骤。
(条件是:该表达式会导致临时对象的产生)
这点可以从pTemp中得以验证。
3 凡含有表达式执行结果的临时对象,应该保留到对象的初始化完成为止。
正是因为有临时对象的存在,会导致程序执行比较没有效率。这一点从与FORTRAN-77的测试对比可以得出。
但是也不必过于担心,因为现在的编译器都会通过反聚合的方法来加以优化。