在C++中“Const”的用法有多少?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (18)

作为新手C ++程序员,有一些对我来说看起来仍然很模糊的构造,其中之一就是const。你可以在很多地方使用它,并且有许多不同的效果,这对于初学者来说几乎是不可能的。一些C ++大师会不会一次性解释各种用法以及是否和/或为什么不使用它们?

提问于
用户回答回答于

试图收集一些用途:

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

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; }
};

说明:只要原始数据和copie对象的数据保持不变,您可能希望在复制某些内容时共享数据。一旦对象中的一个更改了数据,您现在需要两个版本:一个用于原始文件,另一个用于复制。也就是说,你复制于任一对象,使他们现在都有自己的版本。

使用代码

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将更喜欢non-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) {
    // ...
}
用户回答回答于

在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。这有助于但不妨碍你修改你班级的实例。

扫码关注云+社区