You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当实参匹配两个重载函数时,Rvalue reference参数是否优先于Lvalue reference参数?

问题:右值引用参数在重载匹配中是否优先于左值引用参数?

问题背景

当实参同时匹配两个重载函数时,右值引用(Rvalue reference)参数是否优先于左值引用(Lvalue reference)参数?

示例代码

#include <iostream>
#include <cstdint> 
#include <cstring> 
class String{
    public:
        String() = default;

        String( const char * string){                         
            printf("Created!\n");
            m_size=strlen(string); 
            m_data=new char[m_size]; 
            memcpy ( m_data, string , m_size) ; 
        }
        // 若调用Entity的第一个构造函数,会触发该拷贝构造函数
        String(const String& otherObject ){
            printf("Copied!\n");
            m_size=otherObject.m_size;       
            m_data=new char[m_size];   
            memcpy ( m_data, otherObject.m_data , m_size);  
        }
        // 若调用Entity的第二个构造函数,会触发该移动构造函数
        String(String&& AutoTempObject){ 
            printf("Moved!\n");
            m_size=AutoTempObject.m_size;  
            m_data=AutoTempObject.m_data; 
            AutoTempObject.m_size=0;       
            AutoTempObject.m_data=nullptr; 
        }

        ~String(){std::cout<<"Destroyed!\n"; delete[] m_data; }
        
        void Print1(){
            for (uint32_t i = 0 ; i < m_size ; i++){ std::cout << m_data[i]; }
            std::cout<< '\n';
        }
    private: 
        char * m_data;
        uint32_t m_size;  
};

class Entity{
    public:
        // Entity的第一个构造函数
        Entity(const String& StringObject) : m_name(StringObject) {}
        // Entity的第二个构造函数
        Entity(String&& StringObject) : m_name( std::move(StringObject) ) {}

        void print(){ m_name.Print1(); }

    private:
        String m_name; 
};

int main(){
    // 该声明会先调用Entity的某个构造函数,再相应触发String的某个构造函数
    Entity e1(String("StackOverFlow"));
}

观察与疑问

  • 移除Entity的第2个构造函数时,程序会调用Entity的第1个构造函数;
  • 同时保留Entity的两个构造函数时,程序会调用第2个构造函数;
  • 由上述两点可知,实参String("StackOverFlow")同时匹配Entity两个构造函数的参数;
  • 但实例化Entity对象时并未触发编译错误,而是优先调用了第2个构造函数,请问该现象的原因是什么?

解答

这是C++重载决议机制的规则导致的,核心逻辑是编译器会优先选择与实参匹配度更高的重载函数:

  1. 实参的类型属性:String("StackOverFlow")是一个临时对象,属于右值。它既可以绑定到const String&(const左值引用),也可以绑定到String&&(右值引用)。
  2. 匹配优先级差异:根据C++标准,右值绑定到右值引用属于精确匹配,不需要任何隐式转换或限定符调整;而绑定到const左值引用是一种兼容性匹配,优先级低于精确匹配。因此编译器会优先选择接受右值引用的构造函数(即Entity的第二个构造函数)。
  3. 无右值引用重载时的降级逻辑:当你移除Entity的第二个构造函数后,编译器没有更匹配的选项,才会退而求其次选择接受const左值引用的构造函数,这就是此时程序调用第一个构造函数的原因。

结合你的代码场景:

  • 保留两个构造函数时,临时右值String("StackOverFlow")匹配Entity(String&&),随后通过std::move(StringObject)触发String的移动构造函数;
  • 移除第二个构造函数时,只能匹配Entity(const String&),进而触发String的拷贝构造函数。

内容的提问来源于stack exchange,提问作者Crackie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:07:47