起初,我的印象是成员变量通常应该是C ++类中的const,除非我希望它的成员函数在内部为每个对象修改这些变量(我通常将这些变量置于私有中)。
但我现在发现我可能一直都错了。例如我不能再分配给这样的对象了。我甚至不能做动作分配。
说std :: string。你可以这样做:
std::string foo("foo");
foo = std::string("bar");
这必须暗示内部,std :: string只有非const成员变量吗?
我的想法是否正确?作为C ++的新手,它的新思维有点奇怪。 const的目的可能不是我想象的那样。
那么拥有const成员变量的实际目的是什么?
答案 0 :(得分:6)
成员通常不应该是C ++类中的const吗?
我建议您忽略变量如何声明“通常”。 const
出现的频率不会决定您要声明的 next 变量是否为{{1} }}
如果在整个程序执行初始化后它们的值不应该更改,那么成员应该是const
。否则,它们不应该是const
。这是数据的语义属性,您决定是否变量const
的唯一标准是变量在值变化方面的性质。
可能会改变,还是会保持不变? 在后一种情况下,一定要改为const
。
这必须暗示在内部,std :: string只有非const成员变量吗?
否,它并不意味着它,尽管可能恰好是const
的情况。
重要的是,您的班级中只有 std::string
成员(当然,只要你想从它移动而你的类封装了一些资源),所以实际可以用于判断对象是否已被移动的那些成员是可修改的。
当你从一个物体移动时,你剩下的就是一个骨架。移动构造函数或移动赋值运算符需要一种方法来“标记”此移动对象作为框架。通常,这自然地来自于从对象移动的“窃取内容”的过程,即复制一些指针并将它们设置为null - 这样,析构函数和赋值运算符将不会尝试释放它们。为了将移动的对象标记为“僵尸”,显然你需要一些可修改的成员变量。
但是,还在您的班级中有一些const
成员也没有错。 const
是一个重要的修饰符,它可以使程序的语义更加清晰,并且您的程序不太可能破坏它。 在适当的时候(即,在初始化后,只要A变量的值在整个程序执行期间不会发生变化),使用。
简单地说,const
成员变量不会被移动构造函数或移动赋值运算符修改(实际上,它们不会被任何函数修改);但同样,这并不意味着他们不能出席。
答案 1 :(得分:1)
const对象是您不想更改的对象,它们在程序执行期间保持不变。您可以在类的构造函数的成员初始化列表中为它们分配值,但不能超出该值。如果您有一个可以具有不同值的变量,则不应使用const。
答案 2 :(得分:1)
我的印象是成员变量通常应该是C ++类中的const,除非我想要它的成员函数来修改这些变量
您忘记的是赋值运算符(包括默认值)是一个成员函数。例如:
struct Foo {
const int i = 0;
Foo& operator =(const Foo& src)
{
if (&src == this)
return *this;
i = src.i;
return *this;
}
};
由于赋值运算符是一个成员函数,它显然必须能够修改Foo::i
。如果没有,则无法调用它。请注意,鉴于Foo
个对象a
和b
,请执行以下操作:
a = b;
实际上,实际上是语法糖:
a.operator= (b);
另请注意,默认分配运算符在这种情况下会被删除,因为Foo::i
是const
。这意味着如果你自己不写一个,Foo
完全没有赋值操作符。
答案 3 :(得分:1)
我首先建议您查看this related question的答案。
快速而肮脏的答案是const成员属性包含在初始化对象后仍保持不变的值。复制操作试图执行一个动作,该动作导致构造一个新对象,然后将旧对象的值分配给新对象(在隐式复制构造函数体中)。您最有可能想要的解决方案是创建一个显式的复制构造函数,它将原始对象作为参数并初始化初始化列表中的const属性值。
复制构造函数的示例:
ClassWithConstantProperties( const ClassWithConstantProperties &orig) :
constProperty1(orig.constProperty1)
constProperty2(orig.constProperty2)
{
}
This tutorial更全面地解释了C ++中隐式定义的类构造函数,并且也是一个优秀的C ++参考页面。
答案 4 :(得分:1)
这取决于对象,但一般来说,当你写的时候
对象的代码,你负责其不变量。
我很少使用const
或引用成员,但它们是
在不支持作业的课程中完全可以接受。
通常,const
用作逻辑const,而不是按位const。
const更像是你和你客户之间的契约,
而不是保护你自己的东西。在这
感觉,有const函数,返回const引用,和
将const引用作为参数很有意义。最佳
参数上的level const或类中的const并不是真的
然而,这意味着很多。
答案 5 :(得分:0)
类的数据成员描述该类型的对象的状态。 const
数据成员意味着对象具有一些永不改变的状态。这不是很常见。通常const
成员也是static
。
使用const
数据成员唯一可以做的就是将其初始化为构造函数的成员初始化列表。
您可以从另一个std::string
分配给std::string
,这意味着它的副本分配运算符不会对其const
数据成员执行任何操作(因为它当然可以'吨)。
具有const
数据成员的类或结构将不具有隐式默认的复制赋值运算符。编译器无法分配给您的const
数据成员,因此它只是说“如果您要分配,则必须自己定义。”
答案 6 :(得分:0)
在构造后不应在类内更改值时使用常量变量 一些例子:数值常数(pi,e)和参考。
struct Database_Record
{
Database_Record(const std::string& table_name)
: m_table_name(table_name)
{ ; }
const std::string& get_table_name(void) const
{ return m_table_name; }
private:
const std::string m_table_name;
};
在上述表示数据库记录的结构中,它有一个与记录关联的表名,在初始化后不能改变;这可以防止将记录写入错误的表。