通过指向 const 的指针释放内存是一个好习惯吗

发布于 2024-08-22 05:01:43 字数 644 浏览 5 评论 0原文

有很多问题讨论 C 和 C++ 处理指针常量删除的细节,即 free() 不接受它们以及 deletedelete[] 会执行此操作,并且常量性不会阻止对象销毁。

我感兴趣的是您是否认为这样做是一个好的做法,而不是语言(C 和 C++)允许的做法。

指向 const 删除的参数包括:

  • Linus Torvalds 的 kfree() 与 C 的 free() 不同,它采用 void const* 参数因为他认为释放内存不会影响所指向的内容。
  • free() 是在 const 关键字引入之前设计的。
  • C++ 的删除运算符允许删除 const 数据。

反对它的论点包括:

  • 程序员不希望在向数据传递指向 const 的指针时修改(或删除)数据。
  • 许多人认为指向 const 的指针意味着不获得数据的所有权(但并非非 const 意味着获得所有权)。
  • 这是大多数库和现有代码中常见的做法。

请在您的回复中充分论证,并可能参考当局。我的目的不是在这里发起民意调查。

There are many questions discussing the details of C and C++ dealing with pointer-to-const deletion, namely that free() does not accept them and that delete and delete[] do and that constness doesn't prevent object destruction.

What I am interested on is whether you think it is a good practice to do so, not what the languages (C and C++) allow.

Arguments for pointer-to-const deletion include:

  • Linus Torvalds' kfree(), unlike C's free(), takes a void const* argument because he thinks that freeing the memory does not affect what is pointed to.
  • free() was designed before the introduction of the const keyword.
  • C++'s delete operators allow deletion of const data.

Arguments against it include:

  • Programmers do not expect data to be modified (or deleted) when they pass a pointer-to-const to it.
  • Many think that pointer-to-const implies not getting ownership of the data (but not that non-const would imply getting ownership).
  • This is the common practice seen in most libraries and existing code.

Please argument well in your responses and possibly refer to authorities. My intention is not to start a poll here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

已下线请稍等 2024-08-29 05:01:43

使用正确的策略来结束对象的生命周期是一个很好的做法。对于动态对象,这意味着删除您新建的内容,释放您分配的内容,等等。该对象是否为 const 对其生命周期是否应结束没有影响。

常量或易失性是存在于对象生命周期内的属性,并以删除表达式或对 free 的调用结束。无论您对此事有何看法,也无论其他语言的工作方式如何,这就是 C++ 对象模型的工作方式。一个简单的例子来展示这一点,即该语言如何将删除表达式转换为运算符删除调用:

#include <new>
void* operator new(std::size_t size);
void operator delete(void* p);

int main() {
  delete new int(); // int* to void*, since this is also an allowed
  // implicit conversion, it may not be clear what is happening

  // however, these are clearly not implicit conversions:
  delete new int const();          // int const         * to void*
  delete new int volatile();       // int       volatile* to void*
  delete new int const volatile(); // int const volatile* to void*
}

另一个例子,但可能不太清楚,是为什么不能在 const 上重载 ctor:

struct S {
  S() const; // not allowed
};

对象仅在创建后才是 const(也称为其生命周期开始) ; 在 ctor 正常返回时发生)且在其被销毁之前(也称为其生命周期结束;在进入 dtor 时发生)。在该生命周期之前或之后,您可能有一个 T const* 类型的指针(例如),但它不指向对象,并且取消引用它是 UB。

同样的推理过程也适用于 C,只不过您必须考虑到 C 已有大约 40 年的历史,并且在这段时间的大部分时间里成功地保持了大量的一致性。

(我相信这个问题是主观的和争论性的,并且会投票以这种方式结束它,除非我显然帮助了引发讨论;因此以 CW 身份回答。)

It is a good practice to use the proper strategy to end the lifetime of an object. For dynamic objects this means delete what you new, free what you malloc, and so forth. Whether that object is const or not has no affect on whether its lifetime should end.

Being constant or volatile are properties that exist within an object's lifetime, and that ends with a delete-expression or a call to free. Regardless of your own views on the matter or how things work in other languages, this is how C++'s object model works. A simple example to show this is how the language translates delete-expressions into operator delete calls:

#include <new>
void* operator new(std::size_t size);
void operator delete(void* p);

int main() {
  delete new int(); // int* to void*, since this is also an allowed
  // implicit conversion, it may not be clear what is happening

  // however, these are clearly not implicit conversions:
  delete new int const();          // int const         * to void*
  delete new int volatile();       // int       volatile* to void*
  delete new int const volatile(); // int const volatile* to void*
}

Another example, but perhaps less clear, is why you cannot overload ctors on const:

struct S {
  S() const; // not allowed
};

An object is only const after it is created (aka its lifetime begins; happens when the ctor returns normally) and before it is destroyed (aka its lifetime ends; happens as the dtor is entered). Before or after that lifetime you may have a pointer of type T const* (for example), but it does not point to an object and dereferencing it is UB.

The same line of reasoning applies to C, except you have to consider that C has roughly 40 years of history and has succeeded in maintaining a large amount of consistency for much of that time.

(I believe this question is subjective and argumentative and would vote to close it that way, except I apparently helped spark the discussion; so answering as CW.)

成熟的代价 2024-08-29 05:01:43

我从来没有真正理解反对删除(或释放)常量指针的论点。更准确地说,我在某种程度上看到了理性,但在我看来,它们同样适用于对象中的 const 成员或块中的 const 变量,而且我从未见过有人争论这些不应该被破坏,并且它们的记忆当包含对象被删除或执行离开其包含块时释放。

管理对象的逻辑可变性(即常量或非常量)和管理其生命周期(即使用对象变量、智能指针——which and one——或原始指针)这两个问题似乎与我无关。

换句话说,如果

{
    Foo const x;
    ...
}

是有效且良好的风格。为什么

{
    Foo const* xptr = new Foo;
    ...
    delete xptr;
}

不是好的风格(使用足够的智能指针而不是原始指针,但这是另一个问题)。

I've never really understood the arguments against deleting (or freeing) a const pointer. More precisely, I somewhat see the rational but it seems to me that they apply equally well to a const member in an object or a const variable in a bloc, and I've never see anybody argue that those should not be destroyed and their memory freed when the containing object is deleted or the execution leaves their containing block.

The two issues of managing the logical mutability of objects (i.e. const or not) and managing their life length (i.e. use an object variable, a smart pointer -- which and one -- or a raw pointer) seems unrelated to me.

In other words, if

{
    Foo const x;
    ...
}

is valid and good style. Why would

{
    Foo const* xptr = new Foo;
    ...
    delete xptr;
}

not be good style (using an adequate smart pointer instead of a raw one, but that is another issue).

橘味果▽酱 2024-08-29 05:01:43

好吧,这里有一些相关的内容可能太长,无法放入评论中:

  1. 不久前,通过指向 const 的指针释放内存的做法是明确禁止的,请参阅 这位博士。 Dobb 的文章,“语言法”(:)) 部分

  2. http://groups.google 上已进行过两次相关讨论.ru/group/comp.lang.c++.moderated“删除常量指针?”“为什么可以在 const 指针上调用删除操作符” (两者实际上都处理这种情况有问题,即指向 const 的指针)。

  3. 我自己的观点(因为您正在要求参数):在任何给定上下文中相关操作的可能性是由类或函数的(在文档中显式或隐式定义的)契约定义的,而不仅仅是由方法签名或参数类型。

Well, here's some relevant stuff possibly too long to fit into a comment:

  1. Some time ago the practice to free memory via a pointer-to-const was plain forbidden, see this dr. Dobb's article, the "Language Law" ( :)) part.

  2. There has twice been a relevant discussion on http://groups.google.ru/group/comp.lang.c++.moderated: "Delete a const pointer?", "Why can operator delete be called on a const pointer" (both actually deal with the case in question, i.e. pointer to const).

  3. My own point (since you are asking for arguments): possibility of the operation in question in any given context is defined by the (explicitly or implicitly defined in the documentation) contract of a class or a function, not by just the method signature or parameter types.

心凉 2024-08-29 05:01:43

常量和生命周期是两个不同的东西。如果该对象的所有者认为该对象没有理由生存,我认为释放 const 对象没有问题(就像本地的 const 对象在超出范围时将被“释放”一样) )。

至于 free() 不采用 const 指针,我认为人们可能会争辩说,这可能是标准委员会的疏忽,或者那是因为它需要与 malloc() 返回的 if 指针相同。

Constness and lifetime are two different things. I see no problem freeing a const object if the owner of that object decides the object has no reason to live (the same way a const object that's a local will get 'deallocated' when it goes out of scope).

As far as free() not taking a const pointer, I think that one could argue either that that might have been an oversight of the standards committee or that that's because it takes the same kind if pointer that malloc() returns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文