类中的这两个成员函数: const int fun(){} 和 int fun() const{} 一样吗?不一样的话区别在哪里?

作者&投稿:貊使 (若有异议请与网页底部的电邮联系)
int fun(const int)和int fun(int) const的区别~

const int fun(){} 表示函数不能为左值。必须用一个变量来接收他得返回
例如:int a = const int fun();//正确
const int fun();//直接调用会报错
int fun() const{}这个表示类中的const成员也能调用这个函数。

左值右值C++ 2008-02-29 17:30:11 阅读38 评论0 字号:大中小 订阅
什么情况下返回指针?什么情况下返回引用?指针和引用的效果一样么?
这里不仅涉及到引用的实现,也涉及到左值与右值的概念。因为返回值性质的不同决定了引用与指针必定不是相同的。相信你读过我写的这篇文章之后,会有一个比较清醒的认识。

左值(lvalue)和右值(rvalue)最先来源于C语言。最先在C语言中表示位于赋值运算符两侧的两个值,左边的就叫左值,右边的就叫右值。
比如:
int ii = 5; //ii是左值,5是右值
int jj = ii; //jj是左值,ii是右值
上面表明,左值肯定可以作为右值使用,但反之则不然。左值和右值的最早区别就在于能否改变。左值是可以变的,右值不能变,但是这一点在C++中已经不再成立。
在现代C++中,现在左值和右值基本上已经失去它们原本所具有的意义,对于左值表达式,通过具体名字(variant name)和引用(reference)来指定一个对象。非左值就是右值。我们来下一个定义:
左值表示程序中必须有一个特定的名字引用到这个值。
右值表示程序中没有一个特定的名字引用到这个值。
这跟它们是否可以改变,是否在栈或堆(stack or heap)中毫无关系。
1.左值
在下面的代码中:
int ii = 5;
const int jj = ii;
int a[5];
a[0] = 100;
*(a+3) = 200;
const int& max(const int& a, const int& b) //call by reference
{
return a > b ? a : b;
}
int& fun(int& a) //call by reference
{
a += 5;
return a;
}
ii,jj,a[0],*(a+3)这些值,还有函数max的返回值比如max(ii, jj),函数fun的返回值fun(ii)都是左值。因为它们都是被特定的名字所引用的值。
ii,jj,a[0],*(a+3),以及引用了max和fun的返回值的变量就是它们的名字。
注:有人会问max(8, 9)到底是左值还是右值,C++标准规定常量引用
(reference to const)可以引用到右值,所以max(8, 9)似乎应该是右值。但根据我们对左值的定义,说它是左值也对。不管它是左值,还是右值,我们都不能试图去改变它。为了与前面的概念一致,姑且认为它是左值,不可改变的常量左值。
左值有不能改变的,即被const所修饰的左值,比如上面的jj,max(ii, jj),没有被const困住的左值当然是可以改变的。
比如下面的代码都是成立的:
ii = 600;
a[0] = 700;
fun(ii) = 800; //OK!
我们的眼睛没有问题,fun(ii) = 800;完全正确,因为它是可以改变的左值。

2.右值
没有特定名字的值是右值。
看下面的代码:
int fun1() //call by value
{

}
int* fun2() //call by value
{

}
函数fun1的返回值fun1(),函数fun2的返回值fun2()都是右值,它们的值都没有特定的名字去引用。
也许有人会奇怪,fun2()也是右值?前面说的max(a,b)不是左值吗?请看清楚,函数fun2的返回值是pointer,pointer也是call by value,而函数max的返
回值是reference,reference是call by reference。
当然字面上的(literal)值,比如5,8.23,’a’等等也都是右值。
右值最初出现的时候,一个最大的特征就是不可改变。。但时代不同了,标准也变化了。
C++中有可以改变的右值。那就是用户自定义的类(class)的构造函数生成的临时对象。
至于原因,我思考了一下,我想是这样的:我们看类(class)的数据布置结构,会发现它的每一个数据成员都是有名字的,我想编译器在编译的过程中,都会生成一个外部不所知的对这个临时对象右值的名字引用。但当需要改变这个临时对象的时候,这个名字就用上了(实际这时变成了左值,因为有了名字引用)。
比如:
class Point
{
public:
int x;
……//其他各种成员函数
};
我们现在就可以改变右值,用到了匿名的引用名字。
Point().x = 6;//改变了右值

最后说一下引用的机制。很多人都在争论引用是怎么实现的?如果你看看vc做出的反汇编代码,你会发现在机器码的层次,指针与引用的实现是相同。但是,如果你以此断定引用就是指针,那么就错了。的确,引用是靠指针实现的,但是二者有区别。我们讨论引用的问题,一定要在c++的语言层面上讨论,而不能跑到汇编代码中去看。在c++中,引用就是个别名,本身不会另外分配空间。但是在汇编层次,你会发现“引用”有自己的空间。别忘了,你已经离开了c++ 的范围,这样的讨论失去了意义。总之,我们应该明白,c++中的引用就是个别名,具体的实现方法也要取决于编译系统和优化方案。


左值和右值这两个概念我想大家都耳熟能详了,但它们究竟是什么以及如何理解它运用它,一开始大家都会感觉比较困难。所以我想写这篇总结性的文章来帮助大家理解它们。希望对大家有帮助。



首先我们需要理解左值和右值的定义:

左值指的是如果一个表达式可以引用到某一个对象,并且这个对象是一块内存空间且可以被检查和存储,那么这个表达式就可以做为一个左值。

右值指的是引用了一个存储在某个内存地址里的数据。



从上面的两个定义可以看出,左值其实要引用一个对象,而一个对象在我们的程序中又肯定有一个名字或者可以通过一个名字访问到,所以左值又可以归纳为:左值表示程序中必须有一个特定的名字引用到这个值。而右值引用的是地址里的内容,所以相反右值又可以归纳为:右值表示程序中没有一个特定的名字引用到这个值除了用地址。



好这些都是从定义上理解左值右值,那么我们再用这些定义作为我们的理论基础来总结一下哪些是左值,哪些是右值:

左值:

Expression
Lvalue

x = 42
x

*ptr = newvalue
*ptr

a++
a++

b[0] = 100
b[0]

const int m = 10
m

int& f()
The function call to f()




右值:

Expression
Rvalue

100
100

a * b
The expression of a * b

int f()
The function call to f() that does not return reference


以上这些内容都可以用定义来解释为什么这些为左值,而那些为右值。但我要特殊解释一下为什么函数的调用只能作为右值除了这个函数返回的是引用。其实这个也非常好解释,因为如果一个函数返回的值是 内建类型,那么这个返回值是没有办法通过一个名字或者表达式引用到的,同理如果一个函数返回的是一个对象,那么这个对象是一个临时的,也不可能用一个名字访问到。所以函数的调用通常只能作为右值,但如果一个函数返回引用,那么它的返回值就有意义了,因为它是另一个名字的别名,有名字了,所以它就变成了左值。



注意:左值能转化为右值,但反之不行。



好了,讲了这么多我觉得已经足够,但还要多讲一点,这点就是哪些操作符必需左值.

Operator
Requirement

& (unary)
Operand must be an lvalue.

++ --
Operand must be an lvalue. This applies to both prefix and postfix forms.

= += -= *= %= >= &= ^= |=
Left operand must be an lvalue.

const int fun(){} 和 int fun() const{}肯定是不一样的。
1.const int fun(){} 此处的const其实没有意义,等同于 int fun(){} ,因为函数返回的本身是一个固定值,加不加const无所谓,它只是类的一个普通的成员函数而已。
2.int fun() const{} 则是类的常成员函数。它不能更新对象的数据成员,也不能调用该类中没有const修饰的成员函数(这就保证了在常成员函数中绝对不会更改数据成员的值)。
3.如果将一个对象说明为常对象,则通过该常对象只能调用它的常成员函数,而不能调用其他成员函数。

不一样
1、返回值不一样,第一个是const int 第二个是int
2、第一个允许修改类得成员变量的值。第二个不允许
例如:
struct A
{
A(int v):a(v),b(v){}
const int func()
{
a++;//ok 可以修改成员变量值
return a;
}
int func() const
{
b++;//error 不能修改成员变量值
return b;
}
int a;
int b;
};

const int fun(){} 表示函数不能为左值。必须用一个变量来接收他得返回
例如:int a = const int fun();//正确
const int fun();//直接调用会报错
int fun() const{}这个表示类中的const成员也能调用这个函数。

1.const int fun(){} 是函数fun()返回一个int型常量。
2.int fun() const{} 称为常函数。当声明了一个类的常对象后,这个常对象只允许该类的常成员函数操作。

#include <iostream>
using namespace std;

class A{
public:
A(int x,int y):m_n(x),m_x(y){}
void foo(void) const
{

}
const int bar(void)
{

}
ostream& operator>> (ostream& os) const
{
return os<<" "<<m_n<<" "<<m_x;
}
private:
int m_n;
int m_x;
};

int main()
{
A pa(10,20);
//pa.foo();//无法调用 foo()是一个常函数 .是不能修改函数内的成员变量的值//只有const对象才能调用
pa.bar();//可以调用 bar()是一个const int类型的返回值,这个返回值无法修改
pa>>cout<<endl;
}


在C++程序中怎样编写两个向量的内积与外积(成员函数)
如:class Vector { public:Vector(double cx, double cy, double cz) : x(cz), y(cy), z(cz){} Vector OuterProduct(const Vector & v){ double nx = y * v.z - z * v.y;double ny = z * v.x - x * v.z;double nz = x * v.y - y * v.x;return Vector(nx, ...

在C++中为什么不能把两个运算符重载都作为成员函数
对于同一个类的两个成员是不能互相访问私有数据的.但也涉及到一个说法问题 假设这个类为 class Classtest{ private:int value;public:\/\/两个构造函数 :Classtest()Classtest(int j)\/\/设置,和取值函数 :void setvalue(int val)int getvalue()\/\/重载加法操作符 :Classtest operator +(Classtest&b...

MFC中CArray类的成员函数SetSize中的两个参数的解释
回答:分配至少含32个元素的内存空间,如果后续有新元素需加入myArray阵列,可扩展到128个元素内存空间。

请问什么是成员函数的定义?
上例中最后一个“#”号后面还有一个System.out.print("")这是由于这个成员函数在上一行没有结束而且缓冲区没有溢出时将不把输出结果写屏。若你使用print成员函数,却没有得到输出,这时仔细确认一下你是否以""来结束你的输出流。2:不同类型的成员函数 在上例的成员函数声明中你需要注意两点:...

关于MFC中CString的用法
CString提供了两个成员函数CString::LockBuffer和CString::UnlockBuffer来帮助你保护你的数据。当你调用LockBuffer时,你就创建了一个字符串的一个拷贝,然后将引用计数设置为-1,这就“加锁”了该缓冲区。当缓冲区被加锁时,就没有其它的字符串可以引用该字符串中的数据,被加锁的字符串也不能引用其它...

...内存(ram)、光驱(cdrom)等,有两个公有成员函
CPU c,RAM r,CDRAM cd):cpu(c),ram(r),cdram(cd){cout<<"构造了一个computer"<<endl;} computer::computer(computer &p): cpu(p.cpu),ram(p.ram),cdram(p.cdram){ cout<<"调用了复制构造函数"<<endl;} void main(){ CPU m(p6,300,float(2.8));RAM n(1);...

C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是...
C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是“12“,请问该成员函数该怎么写?思路是怎样的呢?... C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是“12“,请问该成员函数该怎么写?思路是怎样的呢? 展开 ...

...两个数据成员以及一个输出姓名和年龄的成员函数
Vince应该是一个字符串或一个字符串变量,可以这样改:……person p("Vince", 10);……或者:……string name = "Vince";person p(name, 10);……

两个包含main函数的文件中的函数调用
这没有别的办法 除非把第2个文件中那两个函数分开放着,不然没法这样做(因为全局main函数不支持重载)C++当中也是如此,如果test和main两个函数都是全局成员,必须分开写才可以由含有另一全局main函数的源文件调用。不过如果不是全局成员而是某个类的成员就不需要了 所以现在写C++都养成习惯,就是说,...

c++中一个空类会有哪些默认的成员函数
Singleton &s = Singleton::getInstance();Singleton copyS(s); \/\/这是会复制一份的,调用了自动生成的复制构造函数Singleton otherS; \/\/这是另一个实例了,调用了自动生成的默认构造函数otherS = s;\/\/这也是会复制一份的,调用了自动生成的赋值函数存在被复制的可能性,并且可以定义很多个变量,那...

金阳县18463168492: 类中的这两个成员函数: const int fun(){} 和 int fun() const{} 一样吗?不一样的话区别在哪里?
宰父杭维沙: const int fun(){} 表示函数不能为左值.必须用一个变量来接收他得返回 例如:int a = const int fun();//正确 const int fun();//直接调用会报错 int fun() const{}这个表示类中的const成员也能调用这个函数.

金阳县18463168492: 类中的这两个成员函数: const int fun(){} 和 int fun() const{} 一样吗?不一样的话区别在哪里? -
宰父杭维沙: 展开1全部 const int fun(){} 和 int fun() const{}肯定是不一样的.1.const int fun(){} 此处的const其实没有意义,等同于 int fun(){} ,因为函数返回的本身是一个固定值,加不加const无所谓,它只是类的一个普通的成员函数而已.2.int fun() const{} 则是类的常成员函数.它不能更新对象的数据成员,也不能调用该类中没有const修饰的成员函数(这就保证了在常成员函数中绝对不会更改数据成员的值).3.如果将一个对象说明为常对象,则通过该常对象只能调用它的常成员函数,而不能调用其他成员函数.

金阳县18463168492: 为什么类里要有const函数,const函数在类里有什么作用? -
宰父杭维沙: const是一个C语言的关键字,它限定一个变量不允许被改变,产生静态作用.使用const在一定程度上可以提高程序的安全性和可靠性.另外,在观看别 人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助.另外CONST...

金阳县18463168492: c++中的类成员函数后面的const是什么意思?? -
宰父杭维沙: 后面的const用来表示不能够在函数内修改该类的成员变量.

金阳县18463168492: C++中,类的const成员函数有什么用 -
宰父杭维沙: 类的非static(静态)成员函数有一个默认实参this,代表当前类对象,const就是修饰这个实参的,意思是函数不能修改这个类对象的值 如下列代码 class cls { ...//省略 return_type func()const; }//在主函数中 cls a; a.func(); 上面函数中const的意思就是不能修改a 也可以等价的这么看 return_type func()const等价于 static return_type func(const *this);

金阳县18463168492: 在类的成员函数后面加 const 是什么意思 -
宰父杭维沙: const是一个C++语言的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性.另外,在观看别人代码的时候,清晰理解const所起的作用,对...

金阳县18463168492: Time sum(const Time &t)const -
宰父杭维沙: 第一个const 调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const Time& t,则不能对传递进来的引用对象进行改变,保护了原对象的属性.第二个const 类成员函数中const的使用 如果一个成员函数的不会修改数据成员,那么最好将其声明为const,因为const成员函数中不允许对数据成员进行修改,如果修改,编译器将报错,这大 大提高了程序的健壮性.

金阳县18463168492: 关于const的用法 -
宰父杭维沙: c/c++语言中的const: 一、概念: 常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的. 二、Const的使用 1、定义常量 (1)const修饰变量,以下两种定义形式在本质上是一样的.它的含义是:const修饰的...

金阳县18463168492: 总结C++中const的用法 -
宰父杭维沙: const有两种用法:class A { public: void fun1()const; void fun2(const int& arg); private: int m_arg; static int m_static; } 先看第一种用法,这个const关键词表示在该成员函数中不可以对该类的数据成员m_arg进行修改.这就是const成员函数的意义...

金阳县18463168492: const函数的作用? -
宰父杭维沙: 的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于改变数据成员的成员函数不能加 ...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网