在升级以下旧 C++ 代码以在现代 Xcode 4.x 编译器下编译时,我发现原始开发人员使用了一个有效但应该避免的编程习惯——现在这是一个错误:
*((USHORT*) pvPixel)++ = uRG; // copy red & green (2 bytes)
我明白了它的意图:将 unsigned short (uRG) 复制到 void 指针 (pvPixel) 指向的地址,然后增加适当的大小(在上述情况下为 2 个字节)。问题是投射 pvPixel 会导致一个临时的,而不是一个左值,这是不再允许的。
最初的开发者在几十个地方使用了这个成语——我可以在短时间内重写。但是,最好提供一个优雅且可读的解决方案,而不是蛮力地重写每一个事件。我可以想到几种可能的替代方案来对每次出现进行强力重写:宏、内联函数,也许是模板?
我的问题是:这个问题是否有任何 C++ 语法/语言解决方案?什么样的方法可以为未来的开发人员生成最清晰的代码?
(两个示例函数,如下):
void PrimSurfaceGDI3::mFillHLine( UINT uRGB, UINT uX, UINT uY, UINT uW )
{
LPVOID pvPixel;
if ( uW > 0 )
{
// obtain a pointer to a specified pixel in the surface
pvPixel = mPtr( uX, uY );
USHORT uRG = *(USHORT*) &uRGB;
BYTE uB = ((BYTE*) &uRGB)[2];
LPVOID pvEnd = (BYTE*) pvPixel + uW * 3;
while (pvPixel < pvEnd)
{
// The two lines below are now ILLEGAL in modern compilers because casting pvPixel to USHORT* or BYTE* results in a TEMPORARY, not an lvalue
*((USHORT*) pvPixel)++ = uRG; // copy red & green (2 bytes)
*((BYTE*) pvPixel)++ = uB; // copy blue (1 byte)
}
}
}
下面,这个成语用于 for 循环的重新初始化语句:
void PrimSurfaceGDI3::mFillVLine( UINT uRGB, UINT uX, UINT uY, UINT uH )
{
LPVOID pvPixel = mPtr( uX, uY );
USHORT uRG = *(USHORT*) &uRGB;
BYTE uB = ((BYTE*) &uRGB)[2];
LPVOID pvEnd = (BYTE*) pvPixel + uH * muScan;
// The reinitialization statement is now ILLEGAL in modern compilers because casting pvPixel to BYTE* results in a TEMPORARY, not an lvalue
for ( ; pvPixel < pvEnd; ((BYTE*) pvPixel) += muScan)
{
*(USHORT*) pvPixel = uRG; // copy red & green (2 bytes)
((BYTE*) pvPixel)[2] = uB; // copy blue (1 byte)
}
}