为什么要一个会替换默认的操作new和delete使用自定义new和delete运营商?
这是继续重载新的和删除在非常有启发性的C++ FAQ:
运算符重载.
本FAQ的后续条目是:
我应该如何编写符合ISO C++标准的自定义new和delete运算符?
注意:答案基于Scott Meyers的"更有效的C++"课程.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
c++ operator-overloading c++-faq new-operator delete-operator
new和delete运算符?这是在延续重载new和delete在非常照明C++ FAQ,操作符重载,以及其后续,一个为什么要更换默认的new和delete操作?
第1部分:编写符合标准的new运算符
第2节:编写符合标准的delete运算符
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法首先开始,所以你的答案很可能被那些提出想法的人阅读.)
注意:答案是基于Scott Meyers的学习'更有效的C++和ISO C++标准.
c++ operator-overloading c++-faq new-operator delete-operator
首先,至少有4-5个主题在SO上有类似的主题.我读了他们每个人,我觉得他们真的没有帮我解决这个具体问题.如果其他人发现重复的问题,我道歉.在我发布之前,我已经完成了我的搜索工作,因为它似乎是一个非常常见的问题.
我在Windows 7上使用Visual Studio .NET 2003.
我有自己的new/delete重载,指向我自己的malloc()和free()的自定义调用.我的新/删除重载在一个头文件中,我已经包含在几个文件中.
问题是,代码库几乎是意大利面,没有简单的方法可以确保所有东西都能使用这些重载.包括第三方库是黑盒子.我们到处都使用STL.
在我的测试中,我发现STL仍在混合调用我自己的新/删除和标准的MSVC新/删除调用.
将我的头文件包含在数千个其他文件中似乎不太现实,这需要花费太长时间.任何人都可以提供一些关于如何正确有效地重载新/全局删除所以一切都使用我的自定义内存管理器的技巧?
这是给出段错误的程序.
#include <iostream>
#include <vector>
#include <memory>
int main()
{
std::cout << "Hello World" << std::endl;
std::vector<std::shared_ptr<int>> y {};
std::cout << "Hello World" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当然,程序本身绝对没有错.segfault的根本原因取决于其构建和运行的环境.
我们在亚马逊上使用构建系统,该系统以几乎与机器无关的方式构建和部署二进制文件(lib和bin).对于我们的情况下,基本上意味着它部署的可执行文件(从上面的程序内置)到和几乎所有的依赖(即共享库)进入.为什么我使用的短语"几乎"是因为共享库,比如,,和可能的其他几个人,从系统(即从可执行选秀权).请注意,这是应该挑选从不过.$project_dir/build/bin/$project_dir/build/lib/libc.solibm.sold-linux-x86-64.so.2/lib64libstdc++$project_dir/build/lib
现在我运行如下:
$ LD_LIBRARY_PATH=$project_dir/build/lib ./build/bin/run
segmentation fault
Run Code Online (Sandbox Code Playgroud)
但是,如果我运行它,而不设置LD_LIBRARY_PATH.它运行正常.
以下是ldd这两种情况的信息(请注意,我编辑了输出,以便在存在差异的地方提及库的完整版本)
$ LD_LIBRARY_PATH=$project_dir/build/lib ldd ./build/bin/run
linux-vdso.so.1 => (0x00007ffce19ca000)
libstdc++.so.6 => $project_dir/build/lib/libstdc++.so.6.0.20 …Run Code Online (Sandbox Code Playgroud) #include <array>
#include <cassert>
class P {
public:
P() : _value(nullptr) {}
~P() { delete _value; }
private:
char *_value;
};
void foo() {
if(std::array<P, 4>().size() != 4)
assert(false);
}
Run Code Online (Sandbox Code Playgroud)
该函数foo()创建一个临时数组来检查程序员所期望的大小.使用-O1或更高的g ++数字表示assert不会失败,并且__assert_fail从生成的代码中删除调用.但是g ++仍然会生成代码来首先构造然后破坏现在未使用的数组.
g++ -std=c++11 -O3 [4.8.2]:
0000000000000000 <_Z3foov>:1
0: 55 push %rbp1
1: 66 0f ef c0 pxor %xmm0,%xmm01
5: 53 push %rbx1
6: 48 83 ec 28 sub $0x28,%rsp1
a: 66 0f 7f 04 24 movdqa %xmm0,(%rsp)1
f: 48 8d …Run Code Online (Sandbox Code Playgroud) 我在一个cpp文件中看到,它external "C" {...}包含了几个函数的定义.
从https://isocpp.org/wiki/faq/mixing-c-and-cpp,我想extern "C"在cpp文件中使用的目的是使附带的C++函数可用于C程序.
链接中的示例显示仅extern "C"包含C++函数的声明,而不是它们的定义
只需声明C++函数extern"C"(在您的C++代码中)并调用它(从您的C或C++代码).例如:
Run Code Online (Sandbox Code Playgroud)// C++ code: extern "C" void f(int); void f(int i) { // ... }
我在开头提到的cpp文件看起来像:
// C++ code:
extern "C" {
void f(int i)
{
// ...
}
void g(int i)
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
是否应该extern "C"包含C++函数的声明或定义?如果是这样,为什么?
我试图从glibc源代码中了解此方法:
26 #if LIBM_SVID_COMPAT
27 /* wrapper sqrtf */
28 float
29 __sqrtf (float x)
30 {
31 if (__builtin_expect (isless (x, 0.0f), 0) && _LIB_VERSION != _IEEE_)
32 return __kernel_standard_f (x, x, 126); /* sqrt(negative) */
33
34 return __ieee754_sqrtf (x);
35 }
36 libm_alias_float (__sqrt, sqrt)
37 #endif
Run Code Online (Sandbox Code Playgroud)
据我了解,如果程序没有sqrt从glibc中找到该函数的有效实现,它将从内核调用硬件函数,即特定的机器函数。这是正确的吗?
还有,这libm_alias_float (__sqrt, sqrt)是什么意思?