我一直在开发一个项目,我绝对必须在C ++中部分开发。我需要开发一个包装器并将一些C ++功能暴露给我的C#app。自.NET即将开始以来,我一直是C#工程师,并且在C ++方面经验很少。在尝试理解语法时,我看起来仍然很陌生。
有什么东西可以让我失去理智,这会阻止我只是拿起C ++并为之奋斗吗?
答案 0 :(得分:28)
C ++有很多陷阱我无法全部枚举。搜索“C#vs C ++”。一些基本的事情要知道: 在C ++中:
答案 1 :(得分:26)
垃圾收集!
请记住,每当您new
某个对象时,您必须负责调用delete
。
答案 2 :(得分:18)
答案 3 :(得分:6)
没有运行时检查
当您尝试执行可能无效但可以在运行时检查的内容时,一个C ++缺陷就是行为 - 例如,取消引用可能为null的指针,或者访问具有索引的数组可能是超出范围。
C#哲学强调正确性;所有行为都应该是明确定义的,在这种情况下,它会对前置条件执行运行时检查,如果失败则抛出明确定义的异常。
C ++哲学强调效率,以及您不应该为可能不需要的任何东西付费的想法。在这种情况下,不会为您检查任何内容,因此您必须自己检查前提条件或设计逻辑以使它们必须为真。否则,代码将具有未定义的行为,这意味着它可能(或多或少)执行您想要的操作,可能会崩溃,或者它可能会破坏完全不相关的数据并导致极难追踪的错误。
答案 4 :(得分:4)
只是抛弃其他一些尚未被其他答案提及的人:
const :C#对const的概念有限。在C ++中,“const-correctness”非常重要。不修改其引用参数的方法应该采用const引用,例如。
void func(const MyClass& x)
{
// x cannot be modified, and you can't call non-const methods on x
}
不修改对象的成员函数应标记为const,即
int MyClass::GetSomething() const // <-- here
{
// Doesn't modify the instance of the class
return some_member;
}
这看起来似乎是不必要的,但实际上非常有用(请参阅下一个临时点),有时也需要,因为像STL这样的库是完全常量的,并且你不能将const事物转换为非常量的东西(不使用const_cast!永远!)。对于呼叫者来说,知道某些内容不会被改变也很有用。最好以这种方式考虑它:如果省略const,则表示将修改 对象。
临时对象:正如另一个提到的答案,C ++更多的是关于价值语义。可以在表达式中创建和销毁临时对象,例如:
std::string str = std::string("hello") + " world" + "!";
这里,第一个+创建一个带有“hello world”的临时字符串。第二个+将临时值与“!”组合在一起,给出一个临时的“hello world!”,然后将其复制到 str 。声明完成后,临时演员将被立即销毁。为了进一步复杂化,C ++ 0x添加了右值引用来解决这个问题,但这超出了这个答案的范围!
您还可以将临时对象绑定到const引用(const的另一个有用部分)。再次考虑上一个功能:
void func(const MyClass& x)
可以使用临时MyClass显式调用它:
func(MyClass()); // create temporary MyClass - NOT the same as 'new MyClass()'!
创建了MyClass实例,堆栈上的 ,func2访问它,然后在func返回后临时MyClass被自动销毁。这很方便,而且通常非常快,因为不涉及堆。注意'new'返回一个指针 - 而不是引用 - 并且需要相应的'delete'。您也可以直接将临时值分配给const引用:
const int& blah = 5; // 5 is a temporary
const MyClass& myClass = MyClass(); // creating temporary MyClass instance
// The temporary MyClass is destroyed when the const reference goes out of scope
Const引用和临时代码经常以良好的C ++风格出现,并且这些工作方式与C#非常不同。
RAII ,异常安全和确定性析构函数。这实际上是C ++的一个有用特性,甚至可能比C#更有优势,因为它也是很好的C ++风格,所以值得一读。我不会在这里介绍它。
最后,我只是抛出这个是指针,而不是引用:)
答案 5 :(得分:2)
从C#或Java进入C ++的人们的传统绊脚石是内存管理和多态行为:
还有很多其他的,但这些可能会让你第一。
答案 6 :(得分:2)
答案 7 :(得分:2)
标题文件!你会发现自己在问,“为什么我每次都需要写两次方法声明?”
答案 8 :(得分:1)
指针和内存分配
...我也是一个C#家伙,我仍然试图用C / C ++中的正确记忆做法。
答案 9 :(得分:1)
以下是托管C ++ here的简要概述。有关使用托管C ++编写非托管包装器的文章here。这里有另一篇关于将Unmanaged与Managed C ++代码here混合的文章。
使用托管C ++会使IMHO更容易用作C#世界的桥梁,反之亦然。
希望这有帮助, 最好的祝福, 汤姆。
答案 10 :(得分:1)
最大的区别是C#的引用语义(对于大多数类型)与C ++的值语义。这意味着对象的复制频率远远高于C#中的对象,因此确保正确复制对象非常重要。这意味着为任何具有析构函数的类实现复制构造函数和operator=
。
答案 11 :(得分:0)
原始内存错综复杂。联合,memset和其他直接内存写入。只要有人将内存写入字节序列(而不是作为对象),就会失去大部分推理代码的能力。
答案 12 :(得分:0)
<强>链接强>
与外部库的链接并不像在.Net中那样宽容,$DEITY
可以帮助你混合使用相同msvcrt的不同风格编译的东西(debug,multithread,unicode ......)
<强>字符串强>
你必须处理Unicode vs Ansi字符串,这些字符串并不完全相同。
玩得开心:)
答案 13 :(得分:-4)
以下并不意味着以任何方式劝阻:D
C ++是Gotcha的雷区,如果你不使用模板和STL就相对温和 - 只是使用面向对象,但即便如此也是一个怪物。在这种情况下,基于对象的编程(而不是面向对象的编程)使其更加驯服 - 通常这种形式的C ++在某些项目中被强制执行(即,不使用甚至有可能被天真地使用的任何特征)。
然而,你应该学习所有这些东西,因为如果你设法穿越雷区,它就是一种非常强大的语言。如果你想了解陷阱,你最好从Herb Sutter,Scott Myers和Bjarne Stroustrup那里获得书籍。系统地检查C++ FAQ Lite将帮助你意识到它确实需要10本左右的书才能成为一名优秀的C ++程序员。