Questions tagged «c++»

有关C ++的问题,C ++是一种静态类型,自由格式,多范式,已编译的通用编程语言。

6
函数无意中使参考参数无效-出了什么问题?
今天,我们发现了仅在某些平台上间歇性发生的讨厌的错误的原因。归结起来,我们的代码看起来像这样: class Foo { map<string,string> m; void A(const string& key) { m.erase(key); cout << "Erased: " << key; // oops } void B() { while (!m.empty()) { auto toDelete = m.begin(); A(toDelete->first); } } } 在这种简化的情况下,问题似乎很明显:B将键的引用传递给A,这会在尝试打印之前删除地图条目。(在我们的示例中,它不是打印出来的,而是以更复杂的方式使用),这当然是未定义的行为,因为key在调用之后是一个悬空的引用erase。 解决这个问题很简单-我们只是将参数类型从更改const string&为string。问题是:首先如何避免这个错误?似乎两个函数都做对了: A没有办法知道是key指它即将销毁的东西。 B可以在将副本传递给之前进行复制A,但是被调用者的工作不是决定按值还是按引用获取参数吗? 有没有我们不能遵循的规则?
54 c++ 

10
为什么“最终”关键字会有用?
似乎Java拥有声明类不可继承的能力,而现在C ++也拥有。但是,根据SOLID中的“打开/关闭”原理,为什么这样做有用?对我来说,final关键字听起来像friend-是合法的,但是如果您使用它,则很可能是设计错误。请提供一些示例,其中不可派生的类将成为优秀的体系结构或设计模式的一部分。
54 java  c++  solid  final 

8
C ++中的垃圾会发生什么?
Java有一个自动GC,它偶尔会停止世界,但会处理堆上的垃圾。现在C / C ++应用程序没有这些STW冻结,它们的内存使用也不会无限增长。如何实现这种行为?如何处理死物?

5
为什么引用计数智能指针如此受欢迎?
如我所见,智能指针已在许多实际的C ++项目中广泛使用。 尽管某种智能指针显然有利于支持RAII和所有权转移,但也存在一种趋势,默认情况下使用共享指针作为“垃圾收集”方式,因此程序员不必考虑太多分配。 为什么共享指针比集成Boehm GC这样的适当垃圾收集器更受欢迎?(或者您是否完全同意它们比实际的GC更受欢迎?) 我知道常规GC相对于引用计数有两个优点: 常规的GC算法在参考循环方面没有问题。 参考计数通常比适当的GC 慢。 使用引用计数智能指针的原因是什么?

3
为什么异常规范不好?
大约10年前回到学校时,他们正在教您使用异常说明符。由于我的背景是其中的一位Torvaldish C程序员,他们顽固地避免使用C ++(除非被迫这么做),所以我只会偶尔散布C ++,并且当我这样做时,我仍然使用异常说明符,因为这就是我所教的。 但是,大多数C ++程序员似乎并不喜欢异常说明符。我已经阅读了各种C ++专家的辩论和论点,例如这些。据我了解,它可以归结为三点: 异常说明符使用与其余语言不一致的类型系统(“影子类型系统”)。 如果您的带有异常说明符的函数抛出了除您指定的内容以外的其他任何内容,则该程序将以不良的意外方式终止。 即将在即将发布的C ++标准中删除异常说明符。 我在这里错过什么还是所有这些原因吗? 我个人的意见: 关于1):那又如何。就语法而言,C ++可能是有史以来最不一致的编程语言。我们有宏,goto /标签,未定义/未指定/实现定义的行为的部落(ho?),定义欠佳的整数类型,所有隐式类型升级规则,特殊情况下的关键字,例如friend,auto ,注册,显式...等等。有人可能会写几本关于C / C ++怪异故事的厚书。那么,人们为什么要对这种特殊的矛盾做出反应呢?与语言的许多其他更危险的特征相比,这是一个较小的缺陷? 关于2):这不是我的责任吗?我可以用C ++编写致命错误的方法有很多,为什么这种特殊情况会更糟?除了编写throw(int)然后抛出Crash_t之外,我还可以声明我的函数返回一个指向int的指针,然后进行一个狂野的,显式的类型转换,然后返回一个指向Crash_t的指针。C / C ++的精神始终是将大部分责任留给程序员。 那优势呢?最明显的是,如果您的函数尝试显式抛出除指定类型之外的任何类型,则编译器将给您一个错误。我认为有关此标准很明确。仅当您的函数调用其他函数而又抛出错误的类型时,才会发生错误。 来自确定性的嵌入式C程序世界,我当然希望更确切地知道函数会给我带来什么。如果有某种语言支持该功能,为什么不使用它呢?替代方案似乎是: void func() throw(Egg_t); 和 void func(); // This function throws an Egg_t 我认为在第二种情况下,调用者有很大的机会忽略/忘记实现try-catch,而在第一种情况下则更少。 据我了解,如果这两种形式之一决定突然引发另一种异常,则程序将崩溃。在第一种情况下,因为不允许它抛出另一个异常,在第二种情况下,因为没有人期望它抛出SpanishInquisition_t,因此该表达式不会在应有的位置被捕获。 如果是后者,在程序的最高级别进行一些最后的捕获似乎并没有比程序崩溃更好的方法:“嘿,程序中的某处引发了一个奇怪的,未处理的异常”。一旦远离异常引发的地方,您将无法恢复程序,唯一可以做的就是退出程序。 从用户的角度来看,如果他们从操作系统中收到一个错误消息框,说“程序终止。地址为0x12345的Blablabla”,或者从您的程序中获得一个错误消息框,指出了“未处理的异常:myclass。 func.something”。该错误仍然存​​在。 随着即将到来的C ++标准,我将别无选择,只能放弃异常说明符。但是,我宁愿听到一些可靠的论据,说明它们为什么不好,而不是“圣洁已经说过了,事实就是如此”。也许对他们的争论比我列出的要多,或者对他们的争论比我所意识到的还要多?

11
为什么C ++具有“未定义的行为”(UB),而其他语言(如C#或Java)却没有?
这篇Stack Overflow帖子列出了C / C ++语言规范声明为“未定义行为”的情况的相当全面的列表。但是,我想了解为什么其他现代语言(例如C#或Java)没有“未定义行为”的概念。这是否意味着编译器设计者可以控制所有可能的方案(C#和Java)或不能控制(C和C ++)?

3
C ++强类型typedef
我一直在尝试一种声明强类型typedef的方法,以在编译阶段捕获某些类的错误。通常,我会将int类型定义为几种类型的id,或者将矢量类型化为位置或速度: typedef int EntityID; typedef int ModelID; typedef Vector3 Position; typedef Vector3 Velocity; 这可以使代码的意图更加清晰,但是经过一整夜的编码之后,人们可能会犯一些愚蠢的错误,例如比较不同类型的id或在速度上增加位置。 EntityID eID; ModelID mID; if ( eID == mID ) // <- Compiler sees nothing wrong { /*bug*/ } Position p; Velocity v; Position newP = p + v; // bug, meant p + v*s but …
49 c++  c++11  type-safety 

5
为什么所有<algorithm>函数仅采用范围,而不采用容器?
中有许多有用的功能&lt;algorithm&gt;,但所有功能都对“序列”(一对迭代器)起作用。例如,如果我有一个容器并且喜欢std::accumulate在其上运行,则需要编写: std::vector&lt;int&gt; myContainer = ...; int sum = std::accumulate(myContainer.begin(), myContainer.end(), 0); 我打算做的是: int sum = std::accumulate(myContainer, 0); 在我看来,这更具可读性和清晰度。 现在我可以看到,在某些情况下,您可能只希望对容器的某些部分进行操作,因此选择传递范围绝对对您有用。但是至少以我的经验来看,这是一种罕见的特殊情况。我通常要对整个容器进行操作。 可以很容易地编写一个包装函数,它接受一个容器,并呼吁begin()和end()就可以了,但是这样的便利功能,不包含在标准库。 我想知道这种STL设计选择背后的原因。

9
关于“告诉,不要问”如何被认为是好的面向对象的解释
这篇博文已在Hacker News上发表,并有几篇推荐。来自C ++的大多数示例似乎与我所教的内容背道而驰。 例如示例2: 坏: def check_for_overheating(system_monitor) if system_monitor.temperature &gt; 100 system_monitor.sound_alarms end end 与好: system_monitor.check_for_overheating class SystemMonitor def check_for_overheating if temperature &gt; 100 sound_alarms end end end C ++中的建议是,您应该更喜欢自由函数而不是成员函数,因为它们会增加封装性。两者在语义上是相同的,那么为什么更喜欢可以访问更多状态的选择呢? 范例4: 坏: def street_name(user) if user.address user.address.street_name else 'No street name on file' end end 与好: def street_name(user) user.address.street_name end …

9
Linux上用于C ++和C开发的IDE的比较:KDevelop,Eclipse,NetBeans,CodeBlocks和Anjuta
我想指出您在Linux上使用全尺寸IDE的经验。 我个人主要与一起工作vim,但是其他程序员希望看到一个真正的IDE。因此,在以下情况下,我想听听您对不同IDE的个人看法以及它们之间的比较: C ++,也许还有一些C开发(不是Java,Python和其他东西) 服务器端编程(无需GUI开发) 在Linux上工作而不是“跨平台”开发。 需要考虑的意见: 它的稳定性如何?如果IDE崩溃,则不需要它。 使用舒适。 强大的调试功能。 与各种构建系统集成 大型项目(数十万行代码的项目)的可伸缩性 我曾经使用过KDevelop,它是一个非常不错的IDE,似乎KDevelop 4是一个巨大的进步。似乎还有许多人宁愿使用Netbeans和Eclipse。
49 c++  ide  linux 

2
仅标头库更有效吗?
假设条件 C ++的仅标头库的优点之一是它们不需要单独编译。 inline仅当函数在头文件*中定义时,在C和C ++中才有意义。 传统上,在C中,使用.c / .h布局,其中标头代表翻译单元的最小公共接口。同样,.cpp / hpp。 题 仅标头库通常比传统布局在代码和执行时间上更有效吗?如果是这样,是否是因为进行了广泛的内联或其他优化? *-在标头中定义函数使编译器可以在编译任何翻译单元时查看实现,并且实际上使内联代码成为可能
48 c++  c  libraries 

8
什么时候不使用虚拟析构函数?
我相信我搜索了许多有关虚拟析构函数的内容,其中大多数提到虚拟析构函数的目的以及为什么需要虚拟析构函数。我还认为,在大多数情况下,析构函数必须是虚拟的。 然后的问题是:为什么c ++默认不将所有析构函数设置为虚拟?或其他问题: 什么时候不需要使用虚拟析构函数? 在这种情况下,我不应该使用虚拟析构函数? 即使我不需要虚拟析构函数,使用虚拟析构函数的成本是多少?


11
当面试官不知道自己问题的答案时该怎么办?[关闭]
昨天我在一次采访中经历了一次糟糕的经历。 面试官问我关于纯虚函数的问题。我说过,它在基类中可能有也可能没有定义,但是派生类应该提供定义,除非它们也想成为抽象类。 但是面试官一直在问:“纯虚拟可以定义吗????”……我说是的。 他再次说:“纯吗?” 我说是。允许的是,如果派生类想要特定的行为,则可以显式调用该函数。 他送我出去。我确信他不知道纯虚函数可以有定义这一事实。 如何对待这种面试官? 问了第二次之后,我应该撒谎说它没有定义吗?:) 还是我应该恪守承诺,放弃工作机会?
48 c++  interview 

3
使用C和C ++进行Android开发[关闭]
我是C,C ++开发人员。我对移动开发感兴趣。我想知道如何使用C和C ++开发Android应用程序,我已经读到它们为C,C ++开发人员提供了一个工具包,但是它不具备Java工具包的所有功能。我应该选择C / C ++开发套件还是最好学习Java,因为它们将来可能无法提供所有功能?
47 c++  c  android 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.