就我在这里和那里阅读而言,应尽可能使用const
。但是,我有一个总是困扰我的案例。
如果成员函数没有改变任何成员变量值,但它在概念上不是const
函数,我应该将其标记为const
吗?
例如:
class Engine{
public:
int status;
};
class Car{
public:
void start() const{
engine_->status = 1;
}
private:
std::unique_ptr<Engine> engine_;
};
编译器将接受start()
的{strong> constness ,因为engine_
指针没有改变。然而,至少IMO似乎是不现实的,在名为start
的类中称为Car
的函数是const
!
这个例子只是一个快速的例子。通常,Car
类的某些内部状态应相应更新,使const
关键字不可行。然而,这个小例子只是为了说明我的想法。
答案 0 :(得分:14)
函数是否应为const
的一个简单指标是:
Type a{...};
Type b{...};
bool comp1 = a == b;
b.some_func(...);
bool comp2 = a == b;
如果comp1
和comp2
不同,则some_func
不是const
。
显然,并非每种类型都有operator==
超载,但大多数都至少有一个概念性的想法,即你会测试它们是否相等。具有不同Car
个状态的不同engine
个实例将不相等。因此,更改engine
状态的函数不是const
。
答案 1 :(得分:5)
在你的情况下,编译器允许你使start()
const由于通过指针的不完美的constness传播。如果用Engine
类型的对象替换指针,则问题将消失。所以答案是否定的,在这种情况下它不应该是const
,因为使用Engine
作为智能指针或实例是内部细节,不应该影响类Car
的公共接口。
据我所知,在可能的情况下应使用const。
这种陈述过于笼统,与任何通用建议一样,不应在每种情况下正式使用。
答案 2 :(得分:4)
在您的示例中,您可能需要std::experimental::propagate_const:
class Car{
public:
void start() { engine_->status = 1; }
private:
std::experimental::propagate_const<std::unique_ptr<Engine>> engine_;
};
然后您的start
不再是const
。
答案 3 :(得分:3)
const
的含义可能会有所不同。
如果保留const
,则为==
。
如果您的类型遵循引用语义并且它不会更改所引用的内容,则某些内容为const
。
如果可以合理的方式在任何右值或左值上使用,则const
为const
。
如果从多个线程使用它是安全的,那么它是const
。
如果汇编为const
,则为const
。
如果对象声称的内部状态不是由内部变异的,则为const
。
所有这些都是合理的规则来决定方法或参数是否是T const*
。
要特别小心的是要了解T*const
和const iterator
之间的区别,并且不要将顶级const作为内部const。它不是const_iterator
const gsl::span<int>
。它不是gsl::span<const int>
,而是const unique_ptr<T>
。它不是unique_ptr<T const>
,而是vector
。
另一方面,vector<const T>
是一个值语义类型;它假装它的缓冲区是它的一部分(即使这是谎言)。它不是const vector<T>
,而是<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mehmet.catchtheball.main">
<RelativeLayout
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:onClick="undo"
android:text="@string/undo" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/button"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="27dp"
android:layout_marginStart="27dp"
tools:textColor="@android:color/background_dark" />
</RelativeLayout>
。