- 引用/使用其他库
- 公开我的库供他人使用
- 字符串处理
- 数据类型转换
- 良好的项目结构
- 要使用的数据结构(例如,在C#中,我经常使用
List<T>
,那我应该使用哪种类似的数据结构?)
实际上,这感觉就像根据你使用的集成开发环境(IDE)不同,指南也不同。所以我真的正在寻找一些更普遍的东西。或者最坏的情况下,专注于使用Microsoft的编译器/IDE。同时请注意,我不需要任何关于通用编程实践的内容(如设计模式、Code Complete等),因为我觉得我在这些主题上已经很熟练了。
List<T>
,那我应该使用哪种类似的数据结构?)我知道你说你掌握了指针和内存管理的技能,但我仍然想解释一个重要的技巧。
作为一个经验法则,永远不要在用户代码中使用new/delete。
每个资源获取(无论是同步锁、数据库连接、一块内存还是其他必须获取和释放的东西)都应该被封装在一个对象中,以便构造函数执行获取,析构函数释放资源。这种技术被称为RAII,基本上是避免内存泄漏的方法。要习惯它。
C++标准库显然广泛使用了这个技术,所以你可以从那里了解它的工作原理。回答你的问题,List<T>
的等价物是std::vector<T>
,它使用RAII来管理其内存。你可以像这样使用它:
void foo() {
// declare a vector *without* using new. We want it allocated on the stack, not
// the heap. The vector can allocate data on the heap if and when it feels like
// it internally. We just don't need to see it in our user code
std::vector<int> v;
v.push_back(4);
v.push_back(42); // Add a few numbers to it
// And that is all. When we leave the scope of this function, the destructors
// of all local variables, in this case our vector, are called - regardless of
// *how* we leave the function. Even if an exception is thrown, v still goes
// out of scope, so its destructor is called, and it cleans up nicely. That's
// also why C++ doesn't have a finally clause for exception handling, but only
// try/catch. Anything that would otherwise go in the finally clause can be put
// in the destructor of a local object.
}
std::string s = "hello world";
int i = (int)42.0f;
这样做有几个原因。 首先,它尝试按顺序执行几种不同类型的转换,你可能会惊讶于编译器最终应用了哪种转换。其次,很难在搜索中找到,第三,它不够丑陋。通常最好避免使用转换,在C++中,它们被制作得有点丑陋,以提醒你这一点。
// The most common cast, when the types are known at compile-time. That is, if
// inheritance isn't involved, this is generally the one to use
static_cast<U>(T);
// The equivalent for polymorphic types. Does the same as above, but performs a
// runtime typecheck to ensure that the cast is actually valid
dynamic_cast<U>(T);
// Is mainly used for converting pointer types. Basically, it says "don't perform
// an actual conversion of the data (like from 42.0f to 42), but simply take the
// same bit pattern and reinterpret it as if it had been something else). It is
// usually not portable, and in fact, guarantees less than I just said.
reinterpret_cast<U>(T);
// For adding or removing const-ness. You can't call a non-const member function
// of a const object, but with a const-cast you can remove the const-ness from
// the object. Generally a bad idea, but can be necessary.
const_cast<U>(T);
int add1(int i) { return i+1; } // The function we wish to apply
void foo() {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5); // Add the numbers 1-5 to the vector
std::list<int> l;
// Transform is an algorithm which applies some transformation to every element
// in an iterator range, and stores the output to a separate iterator
std::transform (
v.begin(),
v.end(), // Get an iterator range spanning the entire vector
// Create a special iterator which, when you move it forward, adds a new
// element to the container it points to. The output will be assigned to this
std::back_inserter(l)
add1); // And finally, the function we wish to apply to each element
}
关于“引用/使用其他库”的回应
有关在 Windows 和 Linux 中显式加载 DLL 的信息包括...
Windows:
函数:LoadLibrary、GetProcAddress、FreeLibrary
Linux:
函数:dlopen、dlsym、dlerror、dlclose
引用和使用其他库,如果你包含源代码,只需将库的头文件 #include 到需要它们的 .cpp 文件中(然后将库的源代码与项目一起编译)。然而,大多数情况下,您可能会使用 .lib(静态库)或 .dll(动态库)。大多数(全部?)DLL 都带有一个 .lib 文件,因此两种类型的过程是相同的:在需要它们的地方包含适当的头文件,然后在链接步骤中添加相关的 .lib 文件(在 Visual Studio 中,我认为您可以将文件添加到项目中)。
我很久没有创建自己的库供他人使用了,所以我会让其他人回答这部分。或者明天我会回来编辑这个答案,因为我明天要为工作创建一个 .lib :)
字符串处理通常使用 std::string 完成。在特殊情况下,您也可以使用旧的 C 样式 sprintf() 函数,但这通常是不鼓励的。
就你所寻找的数据结构而言,可以查看STL(标准模板库)。它包括List、Vector、Map、String等,这些应该对你来说很熟悉。 我不确定你所说的类型转换是什么意思……我假设你知道强制类型转换,所以你肯定指的是更复杂的东西,这可能与你要转换的类型有关。也许其他人可以提供更多信息。