这些 C++ 代码行的含义是什么?是否有其他编写它们的替代方法?
const int& a() const;
int getA() const;
谢谢。
这些 C++ 代码行的含义是什么?是否有其他编写它们的替代方法?
const int& a() const;
int getA() const;
谢谢。
class test {
public:
test() : m_value() {
std::cout << &m_value << std::endl; // print where the attribute is
}
int const & getValue() const {
return m_value;
}
int copyValue() const {
return m_value;
}
void setValue( int value ) {
m_value = value;
}
private:
int m_value;
};
int main() {
test t; // will printout an address [1]
int v1 = t.getValue(); // caller copies the value
int v2 = t.copyValue(); // caller copies the value (itself a copy in hte calle)
int const &r = t.getValue(); // reference to t.m_value
int const &c = t.copyValue();// reference to *copy* [2]
std::cout << v1 << v2 << r << c
<< std::cout; // 0000
std::cout << &v1 << &v2 // 4 pointers, the third is [1] a r *is* t.m_value
<< &r << &c << std::cout; // the rest should be different
t.setValue( 5 );
std::cout << v1 << v2 << r // 0050, v1 and v2 where copies, r *is* t.m_value
<< c << std::cout;
}
标记为[2]的行使用了语言中的一个奇怪特性,即如果您获得对r值(临时)的常量引用,编译器将绑定该临时对象到引用上,并保持其有效,直到引用超出作用域(基本上它将r值临时变量转换为隐藏变量并将引用绑定到它上面)。
我添加了那一行以明确说明行为差异不是由接收端main
进行复制或维护引用造成的,而是由访问器的签名(也要精确)造成的。
两种方法都是实现相同目的的等效方式:
const int& a() const;
int getA() const;
const int& a();
int getA();
然而,扩展编译器验证能力所带来的巨大好处(当您不期望发生更改时不会更改任何内容)显然值得额外使用const。
第二个需要担心的部分是两个函数的返回类型,这是它们之间的主要区别,并且可能是问题产生的动机。让我们将话题转换到另一个函数:
std::string getName() const;
{ return name; }
在这里,返回值可能是类的name属性。返回值是按值返回的,这意味着从该方法返回时将创建属性的副本。当字符串很大且您正在通过值移动许多字符串时,这可能会成为一个问题。此时,出现了按引用返回的机制,它承诺不进行复制:
std::string &getName() const
{ return name; }
这实际上非常有趣:我们返回的是一个引用,而不是对象的副本。引用类似于指针,因此您只需复制一个指针(在 32 位系统中为 4 字节),而不是整个对象。
这非常有前途。但是,它甚至都无法编译。编译器会抱怨您正在返回一个引用,而您承诺该方法是 const 的,因此它将在不应修改其执行对象的情况下进行。这段代码将允许发生非法操作:
Person p( "Baltasar" );
p.getName() = "José";
cout << p.getName() << endl;
这就是为什么const在返回类型中出现作为一种新的有吸引力的选项,它将解决这个问题。常量引用不允许修改其指向的对象,如下所示:
const std::string &getName() const
{ return name; }
const int &getA() const;
int a() const;
const int& a() const;
a()
返回一个对 int
的常量引用。末尾的 const
修饰符表示它不能改变被调用对象的状态。
int getA() const;
与上述描述相同,只不过返回类型为int
,如果收集,则涉及返回变量的复制。
当说无法更改对象状态时,这是什么意思?
class foo
{
int m_Var ;
public:
foo(int arg1) : m_Var(arg1){}
void mutableMethod()
{
m_Var = 20 ; // "this" has the variable m_Var and
// by assigning it a value changes the state of
// m_Var. Changing the state of it's member variable
// is meant changing the state of object.
}
void nonMutableMethod() const
{
m_Var = 20 ; // This assignment is not allowed because of const
// modifier. The method is not allowed to change the
// the state of object on which it is called ( this )
}
};
int
的常量引用。我认为值得一提的是 mutable 成员
,除了 mutable 成员
以外,它不能改变被调用对象的状态。 - Alok Saveconst_cast
哦;-) - Tony Delroy#define CN const
#define CR const& // Constant reference
#define CDa const* // mutable pointer to constant data
#define CPD const * const // constant pointer to constant data
const int& verbose() const;
int CR shorter() CN;
副作用是声明变得更短,随着行数的减少,代码行数也会减少。这只是个人口味问题...但与DMAP宏结合使用时,似乎有优势。
typedef std::map<size_t, float> TypeMap_Of_size_t_vs_float;
TypeMap_Of_size_t_vs_float m_Map;
const TypeMap_Of_size_t_vs_float& verboseIsNice() const
{
return m_MyMap;
}
for each (auto myElement in verboseIsNice())
{
myElement.foo();
}
对比
DMAP(SZ, Flo) m_Map; // typedefs MSZFlo=std::map<size_t, float>
MSZFlo CR tldr() CN { return m_Map; }
fe(el, tldr()) el.foo();
如果不使用自动化和使用迭代器,示例将显示超过333%的差异。
int const& ri = ...;
),返回引用意味着您有可能会出现悬空引用的风险,而返回值则不会。 - James Kanze