当前位置:  开发笔记 > 编程语言 > 正文

在C++中使用"const"的数量是多少?

如何解决《在C++中使用"const"的数量是多少?》经验,为你挑选了3个好方法。

作为一名新手C++程序员,有些结构对我来说仍然非常模糊,其中之一就是const.你可以在很多地方使用它,并且有很多不同的效果,初学者几乎不可能活着出来.一些C++专家会永远解释各种用途以及是否和/或为什么不使用它们?



1> Johannes Sch..:

试图收集一些用途:

将一些临时绑定到引用到const,以延长其生命周期.引用可以是一个基础 - 它的析构函数不需要是虚拟的 - 仍然会调用正确的析构函数:

ScopeGuard const& guard = MakeGuard(&cleanUpFunction);

解释,使用代码:

struct ScopeGuard { 
    ~ScopeGuard() { } // not virtual
};

template struct Derived : ScopeGuard { 
    T t; 
    Derived(T t):t(t) { }
    ~Derived() {
        t(); // call function
    }
};

template Derived MakeGuard(T t) { return Derived(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++库实现了写时复制std::string.两个字符串即使是不同的对象,也会为其字符串数据共享相同的内存.使b非const更喜欢非const版本的operator[]GCC将创建一个后备内存缓冲区的副本,因为我们可以改变它并且它一定不会影响数据a!

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) {
    // ...
}


请解释第一个例子.对我来说没有多大意义.
您能解释一下您的示例中的第一个和第三个用法吗?

2> JaredPar..:

在C++中,const有两个主要用途.

Const值

如果某个值是变量,成员或参数的形式,在其生命周期内不会(或不应该)被更改,则应将其标记为const.这有助于防止对象发生突变.例如,在以下函数中,我不需要更改传递的Student实例,因此我将其标记为const.

void PrintStudent(const Student& student) {
  cout << student.GetName();
}

至于你为什么要这样做.如果您知道基础数据不能改变,那么推理算法要容易得多."const"有所帮助,但不保证会实现.

显然,打印数据到cout不需要太多考虑:)

将成员方法标记为const

在前面的例子中,我将Student标记为const.但是C++如何知道在学生上调用GetName()方法不会改变对象?答案是该方法被标记为const.

class Student {
  public:
    string GetName() const { ... }
};

标记方法"const"可以做两件事.它主要告诉C++这个方法不会改变我的对象.第二件事是现在所有成员变量都被视为标记为const.这有助于但不会阻止您修改类的实例.

这是一个非常简单的例子,但希望它能帮助回答你的问题.



3> Steve Folly..:

注意理解这4个声明之间的区别:

以下2个声明在语义上是相同的.您可以更改其中 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

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有