C ++中“const”的用法有多less?
作为一名新手C ++程序员,有一些对我来说看起来还是很模糊的构造,其中一个是const
。 你可以在很多地方使用它,并有许多不同的效果,初学者几乎不可能活着出来。 一些C ++大师会一次解释一下各种用法和/或为什么不使用它们?
试图收集一些用途:
绑定一些临时引用到常量,以延长其生命。 引用可以是一个基础 – 而且它的析构函数不需要是虚拟的 – 正确的析构函数仍然被调用:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
说明 ,使用代码:
struct ScopeGuard { ~ScopeGuard() { } // not virtual }; template<typename T> struct Derived : ScopeGuard { T t; Derived(T t):t(t) { } ~Derived() { t(); // call function } }; template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }
这个技巧在Alexandrescu的ScopeGuard实用程序类中使用。 一旦临时超出范围,Derived的析构函数被正确调用。 上面的代码忽略了一些小的细节,但是这是很重要的。
用const来告诉别人方法不会改变这个对象的逻辑状态。
struct SmartPtr { int getCopies() const { return mCopiesMade; } };
对于写时复制类使用const ,以使编译器帮助您决定何时何时不需要复制。
struct MyString { char * getData() { /* copy: caller might write */ return mData; } char const* getData() const { return mData; } };
说明 :只要原始数据和复制对象的数据保持不变,您可能希望在复制某些内容时共享数据。 一旦对象之一改变了数据,你现在需要两个版本:一个是原始的,一个是复制的。 也就是说,你复制一个对象的写入 ,所以他们现在都有自己的版本。
使用代码 :
int main() { string const a = "1234"; string const b = a; // outputs the same address for COW strings cout << (void*)&a[0] << ", " << (void*)&b[0]; }
上面的代码片段在我的GCC上打印相同的地址,因为使用的C ++库实现了copy-on-write std::string
。 两个string,即使它们是不同的对象,也为它们的string数据共享相同的内存。 使b
非const将更喜欢operator[]
的非const版本,GCC将创build后备内存缓冲区的副本,因为我们可以更改它,并且不会影响!
int main() { string const a = "1234"; string b = a; // outputs different addresses! cout << (void*)&a[0] << ", " << (void*)&b[0]; }
复制构造函数从const对象和临时对象复制 :
struct MyClass { MyClass(MyClass const& that) { /* make copy of that */ } };
为了使常数,平凡不能改变
double const PI = 3.1415;
通过引用而不是按值传递任意对象 – 以防止可能的昂贵或不可能的值传递
void PrintIt(Object const& obj) { // ... }
C ++中的const有两个主要用途。
Const值
如果一个值的forms是一个variables,成员或参数,它不会(或不应该)在其生命期内被改变,你应该把它标记为const。 这有助于防止对象上的突变。 例如,在下面的函数中,我不需要改变传入的Student实例,所以我把它标记为const。
void PrintStudent(const Student& student) { cout << student.GetName(); }
至于你为什么要这样做。 如果知道底层数据不能改变,那么推理algorithm就容易多了。 “const”有帮助,但不能保证这将实现。
显然,打印数据到cout不需要太多的思考:)
将成员方法标记为const
在前面的例子中,我将Student标记为const。 但是,C ++是如何知道在学生上调用GetName()方法不会改变对象呢? 答案是这个方法被标记为const。
class Student { public: string GetName() const { ... } };
标记一个方法“const”做两件事。 主要是告诉C ++这个方法不会改变我的对象。 第二件事就是现在所有的成员variables都被当作是const标记的。 这有助于但不妨碍你修改你的类的实例。
这是一个非常简单的例子,但希望这将有助于回答你的问题。
注意了解这4个声明之间的区别:
以下两个声明在语义上是相同的。 您可以更改ccp1和ccp2指向的位置,但不能更改它们指向的内容。
const char* ccp1; char const* ccp2;
接下来,指针是const的,所以为了有意义,它必须被初始化为指向某个东西。 你不能把它指向别的东西,但它指向的东西可以改变。
char* const cpc = &something_possibly_not_const;
最后,我们把两者结合起来,所以指向的东西不能被修改,指针也不能指向其他任何地方。
const char* const ccpc = &const_obj;
顺时针螺旋规则可以帮助解开一个声明http://c-faq.com/decl/spiral.anderson.html
正如我在这里读到的,注意到这一点很有用
const
适用于它的左边的任何东西(除了在这种情况下它不适用于它的直接权利)。