标签: delete-operator

C++删除矢量,对象,空闲内存

我完全混淆了在C++中删除东西的问题如果我声明了一个对象数组并且我使用了该clear()函数.我可以确定内存已经发布了吗?

例如 :

tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;

tempVector.pushback(obj1);
tempVector.pushback(obj2);
Run Code Online (Sandbox Code Playgroud)

我可以安全地打电话清除以释放所有内存吗?或者我是否需要逐个删除才能删除?

tempVector.clear();
Run Code Online (Sandbox Code Playgroud)

如果将此场景更改为对象指针,答案是否与上述相同?

vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
Run Code Online (Sandbox Code Playgroud)

c++ vector delete-operator

46
推荐指数
5
解决办法
15万
查看次数

为什么GCC不能优化C++中空指针的删除?

考虑一个简单的程序:

int main() {
  int* ptr = nullptr;
  delete ptr;
}
Run Code Online (Sandbox Code Playgroud)

对于GCC(7.2),在结果程序中有call关于的指令operator delete.对于Clang和Intel编译器,没有这样的指令,空指针删除被完全优化(-O2在所有情况下).你可以在这里测试:https://godbolt.org/g/JmdoJi.

我想知道这样的优化能否以某种方式与GCC一起开启?(我更广泛的动机源于自定义swapvs std::swap可移动类型的问题,其中删除空指针可能代表第二种情况下的性能损失; 有关详细信息,请参阅/sf/answers/3198249771/.)

UPDATE

为了澄清我对这个问题的动机:如果我在移动赋值运算符和某个类的析构函数中使用delete ptr;if (ptr)保护,那么该类的对象将产生3个GCC指令.这可能是相当大的性能损失,例如,在对这些对象的数组进行排序时.std::swapcall

此外,我可以if (ptr) delete ptr;在任何地方写作,但是想知道,这是否也不能成为性能损失,因为delete表达式也需要检查ptr.但是,在这里,我想,编译器只会生成一个检查.

此外,我真的很喜欢delete没有后卫的可能性,这对我来说是一个惊喜,它可以产生不同的(表现)结果.

UPDATE

我只是做了一个简单的基准测试,即排序对象,它们delete在移动赋值运算符和析构函数中调用.来源是:https://godbolt.org/g/7zGUvo

std::sort使用GCC 7.1测量的运行时间和-O2Xeon E2680v3上的标志:

链接代码中存在一个错误,它会比较指针,而不是指向值.更正结果如下:

  1. 没有if后卫:17.6 [s] 40.8 [s], …

c++ null gcc compiler-optimization delete-operator

46
推荐指数
5
解决办法
5976
查看次数

为什么我需要删除[]?

让我们说我有这样的功能:

int main()
{
    char* str = new char[10];

    for(int i=0;i<5;i++)
    {
        //Do stuff with str
    }

    delete[] str;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)
  1. str如果我要结束程序,为什么还需要删除?如果我要退出,我不在乎那个记忆是否会到达满是独角兽的土地,对吧?

  2. 这只是好习惯吗?

  3. 它有更深的后果吗?

c++ memory memory-leaks memory-management delete-operator

45
推荐指数
5
解决办法
2681
查看次数

C++指针数组:删除或删除[]?

Cosider以下代码:

class Foo
{
    Monster* monsters[6];

    Foo()
    {
        for (int i = 0; i < 6; i++)
        {
            monsters[i] = new Monster();
        }
    }

    virtual ~Foo();
}
Run Code Online (Sandbox Code Playgroud)

什么是正确的析构函数?

这个:

Foo::~Foo()
{
    delete [] monsters;
}
Run Code Online (Sandbox Code Playgroud)

或这个:

Foo::~Foo()
{
    for (int i = 0; i < 6; i++)
    {
        delete monsters[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

我目前有最重要的构造函数,一切都在工作,但当然我看不出它是否恰好泄漏...

就个人而言,我认为考虑到我在做什么,第二个版本更合乎逻辑.无论如何,这样做的"正确"方法是什么?

c++ arrays pointers delete-operator

41
推荐指数
5
解决办法
9万
查看次数

delete []运算符的时间复杂度

运营商的时间复杂度delete[]多少?

我的意思是它是如何实现的 - 它是否迭代数组中的所有元素并为每个元素调用析构函数?

此运算符是否对基本类型(int等)和用户定义的类型执行相同操作?

c++ destructor time-complexity delete-operator

41
推荐指数
2
解决办法
3256
查看次数

为什么非放置的`new`和`delete`内置于语言中而不仅仅是常规函数?

为什么非放置new表达式delete表达式实现为内置语言而不是常规函数?

如果我们有...

  • 一种向OS请求/回馈内存的方法

  • 一种显式调用构造函数的方法(放置new)

  • 一种显式调用析构函数的方法(~T())

...为什么不能放置new,delete只是标准库中的常规功能?例:

template <typename T, typename... Ts>
T* library_new(Ts&&... xs)
{
    auto* ptr = /* request enough memory for `T` from OS */;
    new (ptr) T(std::forward<Ts>(xs)...);
    return ptr;
}

template <typename T>
void library_delete(T* ptr)
{
    ptr->~T();
    /* reclaim memory for `T` from OS */
} 
Run Code Online (Sandbox Code Playgroud)

c++ new-operator delete-operator

38
推荐指数
2
解决办法
2897
查看次数

如何控制第三方库代码中的内存分配策略?

上一个标题:"我必须替换全局运算符new和delete以更改第三方代码中的内存分配策略吗?"

简短的故事: 我们需要在不改变源代码的情况下替换第三方库中的内存分配技术.

很长的故事:

考虑使用大量动态分配的内存绑定应用程序(可能是几乎所有可用的系统内存).我们使用专门的分配器,并在任何地方使用它们(shared_ptr容器等).我们对应用程序中分配的每个字节内存都有完全的控制和功能.

此外,我们需要链接第三方帮助程序库.那个讨厌的家伙使得分配在一些标准的方法,使用默认的运营商new,new[],deletedelete[]malloc或别的东西非标准(让我们一概而论说我们不知道这个库如何管理它的堆分配).

如果这个帮助程序库进行足够大的分配,我们可能会出现硬盘抖动,内存碎片和对齐问题,内存bad_alloc不足以及各种问题.

我们不能(或不想)更改库源代码.

第一次尝试:

我们之前从未在发布版本中遇到过这种不圣洁的"hack".使用覆盖运算符的第一次测试new工作正常,但以下情况除外:

  • 我们不知道未来会有什么等待我们(这太糟糕了)
  • 我们的用户(甚至我们的分配器)现在必须按照我们的方式进行分配

问题:

  1. 有没有办法挂钩这些分配而不会重载全局运营商?(本地lib-hook挂钩?)
  2. ......如果我们不知道它究竟用于什么:malloc或者new
  3. 此签名列表是否完整?(并且没有其他事情我们必须实施):

    void* operator new (std::size_t size) throw (std::bad_alloc);
    void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
    void* operator new (std::size_t size, void* ptr) throw();
    void* operator new[] (std::size_t size) throw (std::bad_alloc);
    void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_value) throw(); …
    Run Code Online (Sandbox Code Playgroud)

c++ new-operator delete-operator

37
推荐指数
1
解决办法
2087
查看次数

如何删除void指针?

在C++中删除这样的对象有什么不对吗?

MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
Run Code Online (Sandbox Code Playgroud)

c++ pointers void delete-operator

37
推荐指数
2
解决办法
1万
查看次数

为什么通过基指针删除[]一组派生对象是未定义的行为?

我在C++ 03标准中找到了以下片段5.3.5 [expr.delete] p3:

在第一个备选(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或者行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.


快速回顾静态和动态类型:

struct B{ virtual ~B(){} };
struct D : B{};

B* p = new D();
Run Code Online (Sandbox Code Playgroud)

静态类型pB*,而动态类型*pD,1.3.7 [defns.dynamic.type]:

[ 例如:如果一个p静态类型为"指向"的指针class B指向一个对象class D,B该表达式的动态类型*p是" D."]


现在,再次查看顶部的引用,这意味着如果我正确的话,下面的代码会调用未定义的行为,无论是否存在virtual析构函数:

struct B{ virtual ~B(){} };
struct D : B{};

B* p = new D[20];
delete [] p; // undefined behaviour here …
Run Code Online (Sandbox Code Playgroud)

c++ undefined-behavior dynamic-arrays delete-operator

36
推荐指数
2
解决办法
6448
查看次数

智能指针如何在删除和删除[]之间进行选择?

考虑:

delete new std :: string [2];
delete [] new std :: string;
Run Code Online (Sandbox Code Playgroud)

每个人都知道第一个是错误.如果第二个不是错误,我们就不需要两个不同的运算符.

现在考虑:

std :: unique_ptr <int> x (new int [2]);
std :: unique_ptr <int> y (new int);
Run Code Online (Sandbox Code Playgroud)

是否x知道使用delete[]而不是 delete


背景:当我认为指针的数组类型限定将是一个方便的语言功能时,这个问题浮现在我脑海中.

int *[] foo = new int [2]; // OK
int *   bar = new int;     // OK
delete [] foo;             // OK
delete bar;                // OK
foo = new int;             // Compile error
bar = new int[2];          // Compile error
delete foo; …
Run Code Online (Sandbox Code Playgroud)

c++ smart-pointers shared-ptr delete-operator c++11

33
推荐指数
2
解决办法
4745
查看次数