我们有这个简单的课程:
class MyStr
{
public:
MyStr() { }
wchar_t* pStr;
};
以及使用它的代码:
MyStr ms1, ms2;
ms1.pStr = L"MyStr!";
ms2.pStr = L"MyStr2!";
wchar_t buffer[100];
swprintf(buffer, 100, L"%ls - %ls", ms1, ms2);
将ms1和ms2压入堆栈的程序集如下所示:
FF B5 24 FE FF FF push DWORD PTR [ebp-0x1dc]
FF B5 20 FE FF FF push DWORD PTR [ebp-0x1e0]
它实际上是将MyStr的值/内容(在本例中只是pStr)推送到堆栈上。
如果我们将MyStr更改为只添加一个简单的析构函数:
class MyStr
{
public:
MyStr() { }
~MyStr() { }
wchar_t* pStr;
};
现在传递ms1和ms2的地址,而不是它们的值/内容。
8D 85 24 FE FF FF lea eax,[ebp-0x1dc]
50 push eax
8D 85 20 FE FF FF lea eax,[ebp-0x1e0]
50 push eax
Windows上的Visual Studio以两种方式提供相同的结果(总是传递值/内容),但Linux上的gcc给出了这两种不同的结果。
我们做不到的事情就是更改swprintf行 - 有成千上万行,我们正试图避免更改它们。
答案 0 :(得分:2)
你可以诉诸MACRO
// Forward call to your method
#define swprintf(...) my_swprintf(__VA_ARGS__)
// Your class
class MyStr
{
public:
MyStr() { }
~MyStr() { }
const wchar_t* pStr;
};
// helper function to "fix" parameters
template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value || std::is_pointer<T>::value, T>
normalize(T t) { return t; } // Default one which does nothing
// Fix for your class to return its member.
const wchar_t* normalize(const MyStr& t) { return t.pStr; }
// Your function which (re-)forward to real swprintf with fixed parameter
// Extra parent do avoid macro substitution
template <typename ... Ts>
auto my_swprintf(wchar_t* buffer, const wchar_t* format, const Ts&... args)
{
return (swprintf)(buffer, format, normalize(args)...);
}