C++ 将operator=() 赋值转换为构造的规则到底是什么?例如 Foo foo = bar 实际上会调用 Foo 的构造函数,接受 bar 作为参数(如果存在)。我用谷歌搜索了它是如何工作的,但似乎找不到任何东西。

我无法弄清楚为什么下面的赋值尝试采用构造函数,但没有采用明显正确的构造函数:HandlePtr( 类型&资源 ).使用实际构造语法的构造工作正常,但不能使用赋值运算符。

代码(显然是为了简洁而编辑的):

template< typename TYPE >
class HandlePtr {
public:
    HandlePtr( void ) = default;
    HandlePtr( HandlePtr< TYPE >& other ) = default;
    HandlePtr( TYPE& resource ) {} // generally I would make this explicit, but for testing purposes I took it out
    ~HandlePtr( void ) = default;

public:
    HandlePtr<TYPE>& operator=( TYPE& resource ) { return *this; }
    HandlePtr<TYPE>& operator=( HandlePtr<TYPE>& other ) { return *this; }
};

int main ( void ) {
    int x = 5;
    HandlePtr< int > g( x ); // works
    HandlePtr< int > i;i = x; // works
    HandlePtr< int > h = x; // doesn't work

            // also tried this just out of curiosity:
    HandlePtr< int > h = HandlePtr< int >( x ); // also does not work

    return 0;
}

错误:

shit.cpp: In function ‘int main()’:
try.cpp:19:24: error: no matching function for call to ‘HandlePtr<int>::HandlePtr(HandlePtr<int>)’
   HandlePtr< int > h = x; // doesn't work
                        ^
try.cpp:19:24: note: candidates are:
try.cpp:7:3: note: HandlePtr<TYPE>::HandlePtr(TYPE&) [with TYPE = int]
   HandlePtr( TYPE& resource ) {} // generally I would make this explicit, but for testing purposes I took it out
   ^
try.cpp:7:3: note:   no known conversion for argument 1 from ‘HandlePtr<int>’ to ‘int&’
try.cpp:6:3: note: HandlePtr<TYPE>::HandlePtr(HandlePtr<TYPE>&) [with TYPE = int]
   HandlePtr( HandlePtr< TYPE >& other ) = default;
   ^
try.cpp:6:3: note:   no known conversion for argument 1 from ‘HandlePtr<int>’ to ‘HandlePtr<int>&’
try.cpp:5:3: note: HandlePtr<TYPE>::HandlePtr() [with TYPE = int]
   HandlePtr( void ) = default;
   ^
try.cpp:5:3: note:   candidate expects 0 arguments, 1 provided
try.cpp:20:20: error: redeclaration of ‘HandlePtr<int> h’
   HandlePtr< int > h = HandlePtr< int >( x ); // also does not work
                    ^
try.cpp:19:20: error: ‘HandlePtr<int> h’ previously declared here
   HandlePtr< int > h = x; // doesn't work
有帮助吗?

解决方案

你在忽略这一点 宣言:

T t = u;

这不是赋值运算符。 t = u; 不是声明的子表达式。这里唯一的表达是 u;以及表达式的求值结果 u 用作对象的初始值设定项 t 被宣布。

如果 u 有类型 T, , 然后 t 是从复制构造的 u.

如果 u 没有类型 T, , 然后 u 首先需要转换为类型 T. 。这创建了一个 右值 类型的 T.

您没有任何接受右值的构造函数,因此 T t = u;, ,以及相同的 T t = T(u); 两者都失败了。然而, T t(u) 成功是因为没有创建右值;价值 u 用作构造函数的参数 T(U &).

简化的代码示例:

struct T
{
    T(int &);
    T(T&);
    T();
    T &operator=(int &);
};

int main()
{
    int x = 5;
    T g(x);   // OK, T(int &)
    T g2(5);   // fail, looks for T(int const &)
    T i;      // OK, T()
    i = x;    // OK, T::operator=(int&)
    T h3 = i; // OK, T(T&)
    T h1 = T(x);    // fail, looks for T(T const &)
    T h2 = x;       // fail, identical to previous line 
}

通常你应该使用 const & 作为复制构造函数和赋值运算符的参数;那么所有这些“失败”的情况都会变成“OK”,因为右值可以绑定到 const 引用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top