【发布时间】:2010-12-24 03:56:59
【问题描述】:
如果你只能读取变量而不能写入(类变量),为什么将函数设为 const 如此有用?
【问题讨论】:
-
可以写变量。你就是不能写类变量。
-
我的意思是,但我忘了包括它。
标签: c++ winapi visual-c++ constants
如果你只能读取变量而不能写入(类变量),为什么将函数设为 const 如此有用?
【问题讨论】:
标签: c++ winapi visual-c++ constants
如果你向你的类的实例传递了一个 const 指针或 const 引用,那么它只能调用该类的 const 方法(如果有的话)。
显然,如果您从不关心您的类型的 const 正确性,那么您可以忽略这一点。
我想它也可以帮助编译器在某些情况下优化事物,尽管我对此表示怀疑,即使它确实有帮助,允许那个小的改进(如果有的话)来决定你如何编写你的代码将是一个为时过早的情况大多数情况下的优化。
【讨论】:
这样您就不会“意外”修改类变量之一。这只是一种安全措施。
(如果您在确实修改类的任何数据成员的函数之后使用 const 关键字 - 直接或通过另一个函数调用 - 您将收到编译错误)。
【讨论】:
const_cast 修改对象是合法的,几乎只有在const_cast 的用户首先将const 修饰符添加到最初不是const 的指针或引用中.
一个原因是const 是一种病毒。这意味着如果部分代码是 const 正确的,那么其余代码将无法与该部分互操作。
如果您忽略 const 正确性,您的类与其他库(从标准库开始)协同工作的可能性很小。
例如:
#include <vector>
#include <algorithm>
struct X
{
int n;
bool operator< (X b)
{
return n < b.n;
}
};
int main()
{
std::vector<X> vec;
std::sort(vec.begin(), vec.end());
}
使用 codepad.org
In function 'const _Tp& std::__median(const _Tp&, const _Tp&, const _Tp&) [with _Tp = X]':
/usr/local/lib/gcc/i686-pc-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2642: instantiated from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<X*, __gnu_norm::vector<X, std::allocator<X> > >, __gnu_debug_def::vector<X, std::allocator<X> > >, _Size = int]'
/usr/local/lib/gcc/i686-pc-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713: instantiated from 'void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<X*, __gnu_norm::vector<X, std::allocator<X> > >, __gnu_debug_def::vector<X, std::allocator<X> > >]'
t.cpp:17: instantiated from here
Line 90: error: no match for 'operator<' in '__a < __b'
与标准库兼容的比较运算符必须保证不会修改参数。如果对象在比较时确实发生了变化,那么尝试对它们进行排序将是徒劳的。
另一个例子:你不能通过 const 引用来传递参数,这是传递大对象的传统方式。相反,您必须通过可修改的引用传递参数。现在您将无法将任何类型的临时对象传递给您的函数。
【讨论】:
如果你有一个 const 对象,它只允许 const 成员函数对其进行操作。
【讨论】:
调用者和被调用者之间的合同越多,您可以在代码而不是文档中表达,编译器就越能帮助您遵守该合同(从两端)。隐式this 指针的常量性是其中的重要部分,所有其他参数引用的常量性也是如此。 (当然,按值传递参数的顶级常量不是合同的一部分)
【讨论】:
好处是您可以让编译器强制执行可以修改状态的位置。例如,如果您使用私有数据创建一个类,并且它的所有方法(例如构造函数除外)都是 const,那么您就有一个不可变的数据类型。这样做的好处不是性能之一,而是语义之一。
【讨论】: