ybu*_*ill 3 c++ visual-studio-2005 operator-overloading new-operator
我在VS2005上运行以下代码:
#include <iostream>
#include <string>
#include <new>
#include <stdlib.h>
int flag = 0;
void* my_alloc(std::size_t size)
{
flag = 1;
return malloc(size);
}
void* operator new(std::size_t size) { return my_alloc(size); }
void operator delete(void* ptr) { free(ptr); }
void* operator new[](std::size_t size) { return my_alloc(size); }
void operator delete[](void* ptr) { free(ptr); }
int main()
{
std::string str;
std::getline(std::cin, str);
std::cout << str;
return flag;
}
Run Code Online (Sandbox Code Playgroud)
我输入一个足够长的字符串(比小字符串优化缓冲区长):
0123456789012345678901234567890123456789012345678901234567890123456789
Run Code Online (Sandbox Code Playgroud)
在Debug编译中,进程返回1,在Release配置中,进程返回0,这意味着不调用new运算符!我可以通过设置断点,写入输出/调试输出等来验证这一点......
这是为什么,它是一种标准的符合行为?
经过一些研究,@ bart-jan在他的第二个答案中写道(现在已经删除了,尽管没有人对它进行过一次投票)实际上是正确的.
由于可以很容易地看到我的操作符根本没有在Release中调用,而是调用了CRT版本.(不,对于所有在黑暗中拍摄的人来说,这里没有递归.)问题是"为什么?"
以上是针对动态链接的CRT编译的(这是默认值).Microsoft在CRT DLL中提供了std :: string(以及许多其他标准模板之间)的实例化.查看VS2005附带的Dinkumware标头:
#if defined(_DLL_CPPLIB) && !defined(_M_CEE_PURE)
template class _CRTIMP2_PURE allocator<char>;
// ...
template class _CRTIMP2_PURE basic_string<char, char_traits<char>,
allocator<char> >;
Run Code Online (Sandbox Code Playgroud)
哪里_CRTIMP2_PURE扩展到__declspec(dllimport).这意味着在Release中,链接器链接std::string到构建CRT时实例化的版本,该版本使用默认实现new.
目前还不清楚为什么它不会在调试中发生.正如@Violet Giraffe猜对了,它必须受到一些开关的影响.但是,我认为它是链接器开关,而不是编译器开关.我找不到究竟什么切换很重要.
这里忽略的另一个问题是"它是标准的"吗?尝试VS2010中的代码,operator new无论我编译什么配置,它确实称为我!展望随VS2010的标题表明了Dinkumware 删除了__declspec(dllimport)对上述实例.因此,我认为旧的行为确实是编译器错误,而不是标准.
| 归档时间: |
|
| 查看次数: |
355 次 |
| 最近记录: |