那些C ++行是什么意思?是否有其他方式来编写它们?
const int& a() const;
int getA() const;
感谢。
答案 0 :(得分:10)
这两个是类中成员函数的两个可能签名,它承诺不更改对象本身。在第一种情况下,它将返回对整数(可能是成员属性)的常量引用,引用为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
制作维护引用的副本,而是(也准确) )通过访问者的签名。
答案 1 :(得分:6)
两者都是实现相同目标的等效方式:
const int& a() const;
int getA() const;
您正在返回一个值。方法头右侧的 const 是一个注释函数getA()和一个()不会修改将执行它们的对象(隐藏的this参数)。这在编译时很重要,因为这意味着在编译时会考虑额外的验证。在运行时,上面的函数与这些函数没有区别:
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;
第二个是按值返回,这意味着将在返回时复制 int (4个字节)。第一个意味着将返回对 int (4个字节)的常量引用。可以看出,在这种情况下使用按引用返回而不是按值返回没有性能优势。
根据经验,通过const引用返回始终是安全的,它永远不会比按值返回更昂贵。
答案 2 :(得分:2)
const int& a() const;
a()
返回对int
的const引用。最后的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 )
}
};
此外,常量方法不能通过非const引用返回成员变量。
答案 3 :(得分:2)
关键的区别在于:
getA()
返回一个int
数据值,调用者可以使用该值完全独立于程序的任何其他部分a()
会返回对int
选择的某些a()
的引用:
int x = a()
“示例”当时的int值,逻辑上等同于int x = getA()
const int& x = a()
保存对()返回的变量的引用!保存引用并不总是符合您的期望或想要
GOOD:如果该变量是临时/文字(例如const int& x = a()
,const int& a() { return 3; }
)
GOOD或 BAD?(取决于它在应用中是否有意义):每次稍后读取x
的值时,程序可能会(尝试)从int
内部返回的原始a()
变量重新读取它:如果该变量的值已经更改,那么x
的值也将更改。 (“可能”,因为无论如何,优化者都可以避免这种情况)
UGLY :如果该地址的内存不再存储该变量(例如,它位于new
内存,那是delete
d) ,然后尝试读取x
的值可能会导致不可预测的值或使应用程序崩溃(如果内存地址不再可读)。
a()
和getA()
都是类的成员函数;我们知道这一点,因为只有成员函数可以是const
,这在技术上表明他们不能在不丢弃其常量的情况下更改非mutable
数据成员,但这种限制背后的意图是它们不应该修改对象的调用者可观察值;可变数据通常用于缓存,调试跟踪等。
答案 4 :(得分:0)
我们可以将返回的引用转换为指针,因此从理论上讲,它比返回副本(值)提供更多信息(地址和值)。
并且可以将const ref修改为const_cast可变。
无论如何,编译器都会尝试使用原始寄存器,地址或立即数中的值。
哪个目标的替代方式?确保始终保持正确状态不会增加额外的工作。对于const引用和const,我发现方便使用CR和CN宏。
(253,253,253)(254,254,254)(254,254,254)(253,253,253)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(255,255,255)(255,255,255)
(254,254,254)(255,255,255)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(255,255,255)(255,255,255)(255,255,255)(255,255,255)
(253,253,253)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(255,255,255)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(254,254,254)(255,255,255)(254,254,254)(254,254,254)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(254,254,254)(255,255,255)(255,255,255)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(254,254,254)(255,255,255)(254,254,254)(254,254,254)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(255,255,255)
(254,254,254)(254,254,254)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(254,254,254)(255,255,255)(255,255,255)(255,255,255)
副作用是声明变得越来越短,并且随着行数越来越短,行数也减少了。味道的问题。但是当与DMAP宏结合使用时,它似乎具有优势。
DownloadTask task = new DownloadTask();
String result = null;
try {
result = task.execute("http://www.posh24.se/kandisar").get();
Log.i("Content Downloaded",result);
}
catch(Exception e)
{
e.printStackTrace();
}
Log.i("Result",result);
}
//type of vatiable which we will send to class
public class DownloadTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
String result="";
URL url;
HttpsURLConnection urlConnection = null;
try
{
url=new URL(urls[0]);
urlConnection=(HttpsURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while(data!=-1)
{
char current=(char) data;
result+=current;
data=reader.read();
}
return result;
}
catch(Exception e)
{
e.printStackTrace();
return "Failed";
}
}
vs
#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;
如果不使用自动且使用迭代器,则该示例将显示超过333%的差异。