相关疑难解决方法(0)

什么是"跨度",什么时候应该使用?

最近我有建议span<T>在我的代码中使用's,或者在网站上看到了一些使用span's - 应该是某种容器的答案.但是 - 我在C++标准库中找不到类似的东西.

那么这个神秘的是什么span<T>,以及为什么(或什么时候)使用它是一个好主意,如果它是非标准的?

c++ c++-faq cpp-core-guidelines c++20 std-span

202
推荐指数
3
解决办法
4万
查看次数

如果在循环条件下使用,是否会多次计算strlen?

我不确定以下代码是否会导致冗余计算,还是特定于编译器?

for (int i = 0; i < strlen(ss); ++i)
{
    // blabla
}
Run Code Online (Sandbox Code Playgroud)

strlen()每次i增加时会计算出来吗?

c c++ optimization gcc strlen

108
推荐指数
3
解决办法
6425
查看次数

为什么T *可以在寄存器中传递,但unique_ptr &lt;T&gt;无法传递?

我正在观看Chandler Carruth在CppCon 2019中的演讲:

没有零成本抽象

在该示例中,他举例说明了您对使用std::unique_ptr<int>over和会产生多少开销而感到惊讶int*。该段大约在时间点17:25开始。

您可以看一下他的示例代码对(godbolt.org)的编译结果 -可以看到,确实,编译器似乎不愿意传递unique_ptr值-实际上,底线是只是一个地址-在寄存器内,仅在直接内存中。

Carruth先生在27:00左右提出的观点之一是,C ++ ABI要求按值传递参数(某些但不是全部;也许-非基本类型?而不是在寄存器中。

我的问题:

  1. 这实际上是某些平台上的ABI要求吗?(哪个?)或者在某些情况下可能只是一些悲观?
  2. 为什么ABI这样?也就是说,如果结构/类的字段适合寄存器,甚至单个寄存器,为什么我们不能在寄存器中传递它呢?
  3. 近年来,C ++标准委员会是否曾经讨论过这一点?

PS-为了不给这个问题留下代码:

普通指针:

void bar(int* ptr) noexcept;
void baz(int* ptr) noexcept;

void foo(int* ptr) noexcept {
    if (*ptr > 42) {
        bar(ptr); 
        *ptr = 42; 
    }
    baz(ptr);
}
Run Code Online (Sandbox Code Playgroud)

唯一指针:

using std::unique_ptr;
void bar(int* ptr) noexcept;
void baz(unique_ptr<int> ptr) noexcept;

void foo(unique_ptr<int> ptr) noexcept {
    if (*ptr > 42) { 
        bar(ptr.get());
        *ptr = 42; 
    }
    baz(std::move(ptr));
}
Run Code Online (Sandbox Code Playgroud)

c++ assembly abi calling-convention unique-ptr

80
推荐指数
2
解决办法
2943
查看次数

RAII与垃圾收集器

我最近在CppCon 2016上观看了Herb Sutter关于"Leak Free C++ ..."的精彩演讲,他谈到了使用智能指针实现RAII(资源获取是初始化) - 概念以及它们如何解决大多数内存泄漏问题.

现在我在想.如果我严格遵循RAII规则,这似乎是一件好事,为什么这与C++中的垃圾收集器有什么不同呢?我知道使用RAII,程序员可以完全控制何时再次释放资源,但是在任何情况下都只对垃圾收集器有益吗?它的效率真​​的会降低吗?我甚至听说有一个垃圾收集器可以更高效,因为它可以一次释放更大的内存块,而不是在代码中释放小内存块.

c++ garbage-collection memory-leaks smart-pointers

74
推荐指数
9
解决办法
8577
查看次数

垃圾收集C++中的库

什么免费和商业垃圾收集库可用于C++,每个库的优缺点是什么?

我对来自该领域实际使用的来之不易的教训感兴趣,而不是营销或宣传模糊.

没有必要详细说明与自动垃圾收集相关的常规权衡,但请提及所使用的算法(引用计数,标记和扫描,增量等)并简要总结后果.

c++ garbage-collection libraries

65
推荐指数
4
解决办法
2万
查看次数

C++ 11垃圾收集器 - 为什么和如何

C++ 11的语言功能列表中有:

对垃圾收集和基于可达性的泄漏检测的最小支持

(但似乎没有在GCC和Clang中实施.)

为什么标准委员会引入了这种垃圾收集C++ langauge功能?

C++真的需要GC吗?RAII不是一个优秀的模式(可以统一用于内存和非内存资源,如套接字,文件,纹理......)?

GC会破坏使用RAII的C++代码模式的一致性吗?

有人说GC可以派上用场来打破循环依赖,但是weak_ptr为了这个目的,使用智能指针是不是可以呢?

如果抛出异常会发生什么?如何修改堆栈展开语义以考虑GC?

并且还会IDisposable引入类似C#的模式吗?

此外,假设在C++中引入了GC,指针语法会不同吗?例如,我们是否会^像C++/CLI或C++/CX扩展中那样有类似帽子的"指针" ?应该有一种方法可以区分普通的原始指针和"托管"指针,对吧?

c++ garbage-collection c++11

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

finalize()在Java 8中调用强可达对象

我们最近将我们的消息处理应用程序从Java 7升级到Java 8.自升级以来,我们偶尔会遇到一个流在读取时被关闭的异常.记录显示终结器线程正在调用finalize()保存流的对象(进而关闭流).

代码的基本概要如下:

MIMEWriter writer = new MIMEWriter( out );
in = new InflaterInputStream( databaseBlobInputStream );
MIMEBodyPart attachmentPart = new MIMEBodyPart( in );
writer.writePart( attachmentPart );
Run Code Online (Sandbox Code Playgroud)

MIMEWriter并且MIMEBodyPart是本土MIME/HTTP库的一部分. MIMEBodyPart扩展HTTPMessage,具有以下内容:

public void close() throws IOException
{
    if ( m_stream != null )
    {
        m_stream.close();
    }
}

protected void finalize()
{
    try
    {
        close();
    }
    catch ( final Exception ignored ) { }
}
Run Code Online (Sandbox Code Playgroud)

异常发生在调用链中MIMEWriter.writePart,如下所示:

  1. MIMEWriter.writePart() 写入部件的标题,然后调用 part.writeBodyPartContent( this )
  2. MIMEBodyPart.writeBodyPartContent()调用我们的实用工具方法 …

java garbage-collection finalize finalizer java-8

22
推荐指数
1
解决办法
2182
查看次数

`std :: shared_ptr`的自动循环断路器的可行性

C++ 11引入了引用计数的智能指针std::shared_ptr.作为引用计数,这些指针无法自动回收循环数据结构.但是,可以自动收集参考周期,例如PythonPHP.为了将此技术与垃圾收集区分开来,问题的其余部分将其称为循环中断.

鉴于似乎没有为C++添加等效功能的建议,是否有一个根本原因,为什么类似于已经部署在其他语言中的循环断路器不适用std::shared_ptr

请注意,这个问题不能归结为"为什么没有GC for C++",这已经被问过了.C++ GC通常是指一个自动管理所有动态分配对象的系统,通常使用某种形式的Boehm保守收集器实现.有人指出,这样的收集器不适合RAII.由于垃圾收集器主要管理内存,甚至可能在内存不足之前就被调用,并且C++析构函数管理其他资源,依赖于GC来运行析构函数会在最坏情况下引入非确定性和资源不足.它还指出,在存在更明确和可预测的智能指针的情况下,完全不需要GC.

但是,基于库的智能指针循环断路器(类似于引用计数解释器使用的循环断路器)与通用GC有重要区别:

  • 它只关心通过管理的对象shared_ptr.这些对象已经参与共享所有权,因此必须处理延迟的析构函数调用,其确切的时间取决于所有权结构.
  • 由于其范围有限,循环断路器不关心破坏或减慢Boehm GC的模式,例如指针掩蔽或包含偶尔指针的巨大不透明堆块.
  • 它可以选择加入,比如std::enable_shared_from_this.不使用它的对象不必为控制块中的额外空间付费以保存循环断路器元数据.
  • 循环断路器不需要全面的"根"对象列表,这在C++中很难获得.与标记扫描GC不同,它会查找所有活动对象并丢弃其余对象,而循环断路器仅遍历可形成循环的对象.在现有实现中,类型需要以函数的形式提供帮助,该函数枚举对可以参与循环的其他对象的引用(直接或间接).
  • 它依赖于常规的"当引用计数降至零时破坏"语义来破坏循环垃圾.一旦确定了一个循环,就会要求参与其中的对象清除其强大的引用,例如通过调用reset().这足以打破循环并自动销毁对象.要求对象提供并清除其强力引用(根据要求),确保循环断路器不会破坏封装.

缺乏自动循环中断的建议表明该想法因实际或哲学原因而被拒绝.我很好奇原因是什么.为了完整起见,这里有一些可能的反对意见:

  • "它会引入循环shared_ptr对象的非确定性破坏." 如果程序员控制了循环断路器的调用,那么它就不是非确定性的.此外,一旦被调用,循环断路器的行为将是可预测的 - 它将破坏所有当前已知的循环.这类似于shared_ptr析构函数在引用计数降至零后如何销毁基础对象,尽管这可能会导致"非确定性"级联的进一步破坏.

  • "就像任何其他形式的垃圾收集一样,循环断路器会在程序执行中引入暂停." 实现此功能的运行时的经验表明,暂停是最小的,因为GC只处理循环垃圾,所有其他对象都通过引用计数回收.如果永远不会自动调用循环检测器,则循环断路器的"暂停"可能是运行它的可预测结果,类似于破坏大型std::vector运行大量析构函数的方法.(在Python中,循环gc是自动运行的,但有一些API可以在不需要它的代码段暂时禁用它.稍后重新启用GC将获取同时创建的所有循环垃圾.)

  • "循环断路器是不必要的,因为循环不是那么频繁,可以很容易地避免使用std::weak_ptr." 事实上,循环很容易在许多简单的数据结构中出现 - 例如,一个树,其中孩子有一个指向父项的后向指针,或一个双向链表.在某些情况下,复杂系统中的异质对象之间的循环仅偶尔与某些数据模式形成,并且难以预测和避免.在某些情况下,用弱变量替换哪个指针远非明显.

c++ garbage-collection smart-pointers

12
推荐指数
2
解决办法
785
查看次数

为什么C++需要语言修改才能"管理"?

为什么不能在编译器编写的管理需要进行什么管理中的C++代码(即,使其"CLR兼容")?

也许有一些妥协,比如在某些情况下禁止无效指针等等.但所有这些额外的关键词等等.这些新增内容必须解决的问题是什么?

我对某些方面以及可能难以解决的问题有所了解,但我们将非常感谢一个很好的解释!

.net c++ clr c++-cli managed-code

9
推荐指数
1
解决办法
1589
查看次数

为什么必须为存储在堆中的函数的局部变量调用delete?

假设您具有以下功能:

 void doSomething(){
    int *data = new int[100];
 }
Run Code Online (Sandbox Code Playgroud)

为什么会产生内存泄漏?由于我无法在函数外部访问此变量,为什么每次调用此函数时编译器都不会自行调用delete?

c++ memory memory-leaks

6
推荐指数
2
解决办法
5081
查看次数

为什么其他语言没有类似于Java垃圾收集器的自动垃圾收集?

没有垃圾收集器的其他语言背后的原因是什么?

为什么这些其他语言没有内置垃圾收集?为什么程序员有责任收集?

c c# c++ java garbage-collection

3
推荐指数
3
解决办法
2144
查看次数

Rust 的内存管理与编译时垃圾收集有何不同?

我读过 Rust 的编译器在编译时“插入”内存管理代码,这听起来有点像“编译时垃圾收集”。

这两种想法有什么区别?

我看过Rust 有什么而不​​是垃圾收集器?但那是关于运行时垃圾收集,而不是编译时。

garbage-collection rust

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