我正在阅读这个问题删除一个const指针,想要更多地了解delete行为.现在,根据我的理解:
delete expression 分两步进行:
free()通过调用operator delete 释放内存(通常通过调用).operator delete接受一个void*.作为测试程序的一部分,我重载operator delete并发现operator delete不接受const指针.
由于operator delete不接受const指针而delete内部调用operator delete,删除const指针的工作原理是什么?
不delete使用的const_cast内部?
我试图简单地删除我的vector/list/...函数中的每个指针,用超酷的lambda函数编写.
template <typename T>
void delete_clear(T const& cont)
{
for_each(T.begin(), T.end(), [](???){ ???->delete() } );
}
Run Code Online (Sandbox Code Playgroud)
我不知道该怎么填补???的.任何帮助是极大的赞赏!
更新:它应该是这样的:
template <typename Container>
void delete_clear(Container &c)
{
for_each(c.begin(), c.end(), [](typename Container::value_type x){ delete x; } );
c.clear();
}
Run Code Online (Sandbox Code Playgroud) 我遇到了第一个改变传递给:: delete的左值的编译器,但没有将左值归零.这是以下情况:
Foo * p = new Foo();
Foo * q = p;
assert(p != 0);
assert(p == q);
::delete p;
assert(p != q);
assert(p != 0);
Run Code Online (Sandbox Code Playgroud)
请注意,删除操作后p不为零,并且已从其旧值更改.一位同事告诉我,他在使用一些将p改为0xFFFFFFFF的大型机C++编译器以及将p改为0的其他编译器的经验并不罕见.
在C++标准中,它是否允许编译器执行此操作?
通过StackOverflow搜索,我发现了这个问题:为什么不删除将指针设置为NULL?有一个答案提到Bjarne Stroustrup的答复,其中包括声明:
C++显然允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎.
我已经阅读并重新阅读了最终委员会草案C++ 0x标准的第5.3.5和12.5节,但我没有看到"明确"部分.我只是在寻找标准的错误部分吗?或者这些部分中是否存在一系列逻辑,但我只是没有正确连接在一起.
我没有Annotated C++ Reference Manual的副本了.编译器是否可以在ARM中执行此操作?
[编辑:将部分参考从3.5.3更正为5.3.5.我还添加了一个有趣的悖论作为Henk断言删除后p未定义的对立点.
如果将p初始化为null,则存在一个有趣的悖论.
Foo * p = 0;
Foo * q = p;
assert(p == 0);
assert(p == q);
::delete p;
assert(p == q);
assert(p == 0);
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,行为已有详细记录.当delete获得一个空指针时,它假设什么也不做,所以p保持不变.
我刚刚在programmers.stackexchange上遇到过这个问题,并且看到了关于在delete this;成员函数内部进行操作的问题.
根据我的理解,这通常是禁止的,但是在某些情况下这可能是有用的.什么时候会有用,哪些技术原因没有?
我记得在某个地方读过delete NULL要在C++中成为有效的操作是必要的,但是我不能记得为什么它应该如此.有人请提醒我吗?
我有一个类Item,它定义了自己的operator new和operator delete,如下所示:
class Item
{
public:
Item(const std::string &s):msg(s)
{
std::cout<<"Ctor: "<<msg<<std::endl;
}
static void* operator new(size_t size, int ID, const std::string &extra)
{
std::cout<<"My Operator New. ID/extra: "<<ID<<"/"<<extra<<std::endl;
return ::operator new(size);
}
static void operator delete(void* p)
{
std::cout<<"My Operator Delete"<<std::endl;
return;
}
~Item()
{
std::cout<<"Destructor: "<<msg<<std::endl;
}
void Print()
{
std::cout<<"Item::msg: "<<msg<<std::endl;
}
private:
std::string msg;
};
Run Code Online (Sandbox Code Playgroud)
我使用placement new创建了这种类型的对象,然后删除如下:
int main()
{
Item *pI=new(1,"haha")Item("AC Milan");
std::cout<<"before delete"<<std::endl;
delete pI;
std::cout<<"after delete"<<std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是: …
以下代码中的4个类:A,B,C和D.
他们都有一个成员operator new[].
除了,
operator delete[].输出size成员的参数operator new[]和sizeof4个类的参数:
new[] A 40
new[] B 40
new[] C 48
new[] D 48
sizeof(A) 4
sizeof(B) 4
sizeof(C) 4
sizeof(D) 4
Run Code Online (Sandbox Code Playgroud)
差异的原因是size什么?
代码(丑陋我知道):
#include <iostream>
using namespace std;
class A {
int i;
public:
static void* operator new[](std::size_t size) throw(std::bad_alloc) {
cout << "new[] A " << size << endl;
return malloc(size);
}
};
class B {
int i; …Run Code Online (Sandbox Code Playgroud) 我在这里有一段代码,其中我不明白为什么它会导致第22行(delete []语句)出现分段错误.你能解释一下吗?
#include<iostream>
#include<memory>
class A {
size_t a[1000];
public:
virtual ~A() { }
};
class B : public A {
public:
float b;
virtual ~B() { }
};
int main(int argc, char** argv){
A *b;
b = new B[10];
delete[] b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,如果B类没有任何成员变量(即我注释掉"float b;"行),那么代码运行正常.
我的错在哪里?
这是关于非成员函数.我确实理解这是一个实现.但我对背后的逻辑有点困惑?
// why this?
void do_not_use_this_ever ( void ) = delete ;
Run Code Online (Sandbox Code Playgroud)
如果我不想使用某个函数,为什么要声明它然后删除呢?为什么不呢:
// why not this?
// void do_not_use_this_ever ( void ) = delete ;
Run Code Online (Sandbox Code Playgroud)
如果= delete声明一个意图,只需像上面的注释声明相同的意图.
任何人都可以想到一个用例,将非成员函数声明为删除更好,然后根本没有它?
更新
已在这里回答.虽然.两个答案都std::cref用作例子.正如@geza在评论中所说的那样,讨论其他用例也是相当有益的.
以下代码使用编译和链接Visual Studio(2017和2019都使用/permissive-),但不使用gcc或进行编译clang。
foo.h
Run Code Online (Sandbox Code Playgroud)#include <memory> struct Base { virtual ~Base() = default; // (1) }; struct Foo : public Base { Foo(); // (2) struct Bar; std::unique_ptr<Bar> bar_; };foo.cpp
Run Code Online (Sandbox Code Playgroud)#include "foo.h" struct Foo::Bar {}; // (3) Foo::Foo() = default;main.cpp
Run Code Online (Sandbox Code Playgroud)#include "foo.h" int main() { auto foo = std::make_unique<Foo>(); }
我的理解是,in main.cpp中的Foo::Bar必须是完整类型,因为in中尝试将其删除~Foo(),它是隐式声明的,因此在访问它的每个翻译单元中都是隐式定义的。
但是,Visual Studio不同意,并接受此代码。此外,我发现以下更改使Visual Studio代码遭到拒绝:
(1)非虚拟(2)内联-即Foo() …c++ visual-c++ language-lawyer delete-operator incomplete-type
c++ ×10
delete-operator ×10
c++11 ×2
destructor ×2
c++17 ×1
function ×1
lambda ×1
lvalue ×1
new-operator ×1
pointers ×1
stl ×1
this ×1
visual-c++ ×1