2

由于各种无聊的原因,我需要一个装箱的 int 类,它主要用作 int,但它是一个从基类继承的类,因此它可以与对象层次结构的其他部分一起使用。我包含了一个构造函数,它接受一个 int 和一个 int 类型转换,因此我可以轻松地将我的盒装 int 与代码中的常规 int 混合。但是,我看到了一个我无法弄清楚的非常奇怪的行为:当我从一个函数返回装箱的 int 时,我希望它使用我的复制构造函数来引用另一个 BoxedInt。但是,它会将我的装箱 int 转换为 int,然后使用我的 int 构造函数。这会导致问题,因为在我的实际代码库中,我想在这种情况下复制其他基类属性,并且它们会因采用此强制转换/构造函数路径而丢失。这是有问题的代码:

class BoxedInt
{
private:
    int m_int;
public:
    BoxedInt():m_int(0)
    {
        trace(L"Constructed with nothing");
    }

    BoxedInt(int val):m_int(val)
    {
        trace(L"Constructed with int");
    }

    BoxedInt(BoxedInt& val)
    {
        trace(L"Constructed with reference");
        m_int = val.m_int;
    }

    operator int()
    {
        trace(L"Cast to int");
        return m_int;
    }
};

BoxedInt funky()
{
    BoxedInt TempInt = 1;
    return TempInt;
}

int main(int argc, char* argv[])
{
    trace(L"Start");
    BoxedInt test1 = 1;
    trace(L"Copying");
    BoxedInt test2 = test1;
    trace(L"Assigning from return value");
    BoxedInt test3 = funky();
    trace(L"Done");
    return 0;
}

运行时,输出如下:

Start
Constructed with int
Copying
Constructed with reference
Assigning from return value
Constructed with int
Constructed with reference
Cast to int
Constructed with int
Done

因此,当我将一个值分配给另一个值时,会使用基于引用的构造函数,正如我所期望的那样。但是,当我将函数的返回值分配给 BoxedInt 时,由于某种原因,编译器决定强制转换为 int,然后使用 int 构造函数。我的 C++ 生锈了,我无法深入了解这个我似乎无法应对的奇怪编译器决定。有任何想法吗?

4

3 回答 3

9

您的复制构造函数引用了一个非常量,因此它不能被临时调用。的返回值 funky()是临时的,所以不能使用复制构造函数来构造test3.

让复制构造函数接受 const 引用,应该没问题。

于 2013-10-15T16:53:31.283 回答
5

您的复制构造函数采用非常量引用,这意味着您不能将临时绑定到参数,这正是您想要的返回方法所做的。因此,编译器选择了另一条路线。

更改您的复制构造函数:

BoxedInt(const BoxedInt &val) {

事实上,Clang 3.4给出了一个错误,因为BoxedInt test1 = 1;.

于 2013-10-15T16:53:02.927 回答
1

我相信问题(或其中之一)是复制构造函数签名:

BoxedInt(BoxedInt& val)

它应该是

BoxedInt(const BoxedInt& val)
于 2013-10-15T16:53:23.963 回答