C++ 为什么C++;选择将我的返回值强制转换为int?

C++ 为什么C++;选择将我的返回值强制转换为int?,c++,casting,reference,constructor,copy-constructor,C++,Casting,Reference,Constructor,Copy Constructor,出于各种无聊的原因,我需要一个装箱的int类,它主要充当int,但它是一个从基继承的类,因此可以与对象层次结构的其他部分一起工作。我包括了一个接受int的构造函数,以及一个int类型转换,这样我就可以很容易地在代码中混合我的装箱int和常规int。然而,我看到了一个我无法理解的非常奇怪的行为:当我从一个函数返回我的boxed int时,我希望它使用我的复制构造函数引用另一个BoxedInt。但是,它将我的装箱int转换为和int,然后使用我的int构造函数。这会导致问题,因为在我的实际代码库中,

出于各种无聊的原因,我需要一个装箱的int类,它主要充当int,但它是一个从基继承的类,因此可以与对象层次结构的其他部分一起工作。我包括了一个接受int的构造函数,以及一个int类型转换,这样我就可以很容易地在代码中混合我的装箱int和常规int。然而,我看到了一个我无法理解的非常奇怪的行为:当我从一个函数返回我的boxed 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++是生锈的,我很难找到这个奇怪的编译器决定的底部,我似乎无法抵消。有什么想法吗?

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

更改副本构造函数:

BoxedInt(const BoxedInt &val) {
事实上,由于
BoxedInt test1=1,clang3.4

我认为问题(或其中之一)在于复制构造函数签名:

BoxedInt(BoxedInt& val)
应该是

BoxedInt(const BoxedInt& val)

复制构造函数引用非常量,因此 无法使用临时名称调用。的返回值
funky()
是临时的,因此不能使用复制构造函数 构建
test3

让复制构造函数接受常量引用,它应该
确定。

阅读关于explicit关键字的内容编译器不会将返回值强制转换为
int
,而是将其转换。强制转换是您在源代码中编写的命令编译器进行转换的内容。类似地,
操作符int
是一个转换操作符,而不是强制转换。我认为Clang是正确的。复制初始化需要一个可访问的复制构造函数。按照我的解释,这意味着一个可访问的复制构造函数来复制至少在理论上构造的临时文件。@JamesKanze,我完全同意。GCC 4.8.1还抱怨
BoxedInt test1=1应该的。是的。当我写我的答案时,我想知道这一点。我不确定,但我认为他不应该用
int
完成初始化。由于上下文有点特殊,我就顺其自然,认为可能有一个特殊的规则。然而,我只是查了一下,至少在C++11中,情况正好相反;该标准明确指出,被复制的是一个临时值和一个PR值(这意味着它可以绑定到右值引用或常量引用,但不能绑定到非常量引用)。@Cassineri,我自己没有测试过它,但听到这一点很欣慰,谢谢。我觉得自己像个白痴,我注意到我一发布,但现在删除已经太晚了!你们太快了。@Raja我不确定这是不是一个好的参考页。赫伯很好地解释了这些问题,但他使用的例子是,你不应该使用引用开始,const或其他;他对此只字未提的事实可能会向许多读者暗示,在这里使用const引用是一种良好的编程实践。