为什么这个函数在使用这个奇怪的调用初始化成员值的类中?

时间:2017-09-29 19:44:34

标签: c++ class oop pointers

#include <iostream>

using namespace std;

class MyClass {
    int x;
  public:
    MyClass (int val) : x(val) {
        cout << "constructed :" << this << endl;
    }
    int& get() {
        cout << "x is : " << x << endl ;
        return x;
    }
};

int main () {
    MyClass foo = {10};
    foo.get() = 20;
    foo.get();
    foo = 30;
    cout << &foo << endl;
    foo.get();
}

我得到以下输出:

constructed :0x7fffc44ef920
x is : 10
x is : 20
constructed :0x7fffc44ef924
0x7fffc44ef920
x is : 30

为什么foo.get() = 20这是改变&#39; x&#39;的价值的合法途径?在对象foo中?

另外,为什么foo = 30在地址0x7fffc44ef924处构建新对象?这个对象类型是什么?

为什么会这样:cout << &foo << endl;打印在main函数开头实例化的原始MyClass foo对象的地址(地址0x7fffc44ef920)?

你如何引用新的&#39; foo在地址0x7fffc44ef924

2 个答案:

答案 0 :(得分:1)

  

为什么这个foo.get()= 20是改变&#39; x&#39;的价值的合法方式。在对象foo中?

因为您将引用返回到x以及引用的行为方式。事实上,我知道从函数(int &get())返回引用的唯一原因是允许这种行为。例如,如果您正在实现operator []。

,则可以执行此操作

有时你想要返回一个const引用(const int &foo())以避免复制值,但你只能用类或结构来做。

  

为什么这个foo = 30在地址上构造一个新对象   0x7fffc44ef924?这个对象类型是什么?

因为MyClass有一个带有一个int参数的构造函数,所以编译器会将此解释为将int转换为MyClass的方法,这就是这里发生的事情。它等同于foo = MyCLass(int)如果您不想要这种行为,可以将MyClass(int)声明为显式:

explicit MyClass( int val ) {...
  

为什么这个foo = 30在地址上构造一个新对象   0x7fffc44ef924?这个对象类型是什么?

     

为什么会这样:cout&lt;&lt; &amp; foo&lt;&lt; ENDL;打印的地址   原始的MyClass foo对象在main的开头实例化   功能(地址0x7fffc44ef920)?

首先,我上面描述的隐式MyClass(30)用于构造一个新的MyClass对象。该对象的地址恰好具有地址0x7fffc44ef924,然后将新对象复制到旧对象中,位于0x7fffc44ef920。可能如果你打开了优化,你只会看到一个地址,因为编译器会看到创建一个全新的对象然后复制它是一个CPU循环的浪费。

  

你如何引用新的&#39; foo在地址0x7fffc44ef924?

您无法在一行代码中创建和销毁该对象。一旦将其复制到原始对象上,如上所述,它就被删除了。

答案 1 :(得分:0)

通过在构造函数之前添加explicit关键字,将构造函数更改为显式构造函数,如下所示:

explicit  MyClass (int val) : x(val) {
  cout << "constructed :" << this << endl;
}

然后,您将从编译器获得非常有用的消息:

prog.cc: In function 'int main()':
prog.cc:18:22: error: converting to 'MyClass' from initializer list would use explicit constructor 'MyClass::MyClass(int)'
     MyClass foo = {10};
                      ^
prog.cc:21:11: error: no match for 'operator=' (operand types are 'MyClass' and 'int')
     foo = 30;
           ^~
prog.cc:5:7: note: candidate: 'constexpr MyClass& MyClass::operator=(const MyClass&)'
 class MyClass {
       ^~~~~~~
prog.cc:5:7: note:   no known conversion for argument 1 from 'int' to 'const MyClass&'
prog.cc:5:7: note: candidate: 'constexpr MyClass& MyClass::operator=(MyClass&&)'
prog.cc:5:7: note:   no known conversion for argument 1 from 'int' to 'MyClass&&'

阅读并理解它。如果它们没有意义,那么你真的需要更多地学习C ++,例如一个book