请教两道C++拷贝构造函数vs重载赋值操作符=的面试题

首先请教一下概念:比如现在定义了一个class叫Example,然后main()函数里先声明了Example A; 再Example B=A或者Example B(A)。

这里,“Example B=A”自然属于重载赋值操作符=,那么“Example B(A)”是否也属于重载赋值操作符=呢?看到网上有句话叫“当需要拷贝构造函数时,重载赋值操作符也是需要的;反之亦然。”——这个说法是否正确呢?

面试题1:

class Sc
    {
    public:
        int x;
    public:
        Sc(int xx): x(xx) {}
        Sc(const Sc&a) {x=a.x; x++;}
        void operator = (const Sc &a1) {x=a1.x; x--;}
    };
int main()
    {
    Sc a(4);
    Sc b=a;
    cout << b.x << endl;
    return 0;
    }

请问运行之后为什么b.x是5呢?

面试题2:

class String
    {
    public:
        explicit String(char ch, int n=1) {}
        String(const char *p) {}
    private:
        void operator = (const char*) {}
    };
int main()
    {
    String x="aaa";
    return 0;
    }

面试官问:“这段程序显然有问题。那么问题出在哪里呢?explicit,还是constructor,还是operator=呢?”

恳请指点。谢谢大家!

阅读 3.1k
2 个回答
  1. Example B(A) 是调用拷贝构造函数.
  2. Sc b=a; 调用拷贝构造函数, 所以 b.x 初始化为4, 在, x++ 得到 5.
  3. 没有问题, 会使用默认合成的拷贝构造函数. String x="aaa";执行拷贝初始化, 而且拷贝构造函数的参数是const String &. 所以会根据构造函数String(const char *p) {}转换为对应的String对象,在进行拷贝初始化.
    你可以这样测试:
String(const char *p) { 
    std::cout << "run String(const char *p)" << std::endl; 
}

“Example B=A”自然属于重载赋值操作符=,那么“Example B(A)”是否也属于重载赋值操作符=呢?
这里 Example B = A 不是重载赋值,而是隐含的调用了 Example(Example& ) 这个构造函数,如果用户没有定义 就是用合成的函数 bitcopy过去的。同理 Example B(A);

对于这个比较现代的编译器应该都是这么实现的。如果你单独写
Example B;
这是一个声明,但是如果有可用的构造函数(包括是编译器合成的) 那么会自动调用初始化。认为 Example B = A;就存在一次赋值,大概是 Example B = A; 早期会被解释成
Example B;
B = A;
但是从现代编译器的实现上是不正确的,现代编译器没那么傻。

当需要拷贝构造函数时,重载赋值操作符也是需要的;反之亦然.

可否说明出处。Example(Example& )就是拷贝构造函数,这句话的意思是为了兼容上面不同的编译器实现?也就是Example B = A 会出现一次赋值的这种实现。

面试题一:

同样的问题,你理解了上面的就理解了,这道题

面试题二:

应为赋值重载被干掉了,所以可能不兼容上述的多一次赋值的那种编译器实现?

感觉你的这个题目可能有点年代。所以你是在面试哪一家。。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏