首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么我一直收到此错误:从类型为‘FarmAnimal’的右值中初始化类型为'FarmAnimal&‘的非常数引用无效

这个错误是因为你尝试将一个右值(临时对象)赋值给一个非常数引用,而非常数引用只能绑定到左值(具有持久性的对象)。右值是指那些临时创建的、没有持久性的对象,例如函数返回的临时对象或者使用移动语义生成的临时对象。

在C++中,非常数引用只能绑定到左值,这是为了确保引用的稳定性和安全性。因为右值是临时的,可能会在表达式结束后被销毁,如果允许将右值赋值给非常数引用,那么在引用的生命周期内可能会引用一个已经销毁的对象,导致未定义行为。

要解决这个错误,你可以将非常数引用改为常数引用,或者使用移动语义来处理右值。常数引用可以绑定到左值和右值,因此可以接受临时对象的赋值。移动语义是C++11引入的特性,通过std::move函数将右值转换为左值引用,从而可以将其赋值给非常数引用。

以下是一个示例代码,演示了如何使用常数引用和移动语义来解决这个错误:

代码语言:txt
复制
#include <iostream>

class FarmAnimal {
public:
    FarmAnimal() {
        std::cout << "FarmAnimal constructor" << std::endl;
    }
    FarmAnimal(const FarmAnimal& other) {
        std::cout << "FarmAnimal copy constructor" << std::endl;
    }
    FarmAnimal(FarmAnimal&& other) {
        std::cout << "FarmAnimal move constructor" << std::endl;
    }
};

void foo(const FarmAnimal& animal) {
    // do something with the animal
}

int main() {
    FarmAnimal animal;
    foo(animal);  // 正确,将左值animal赋值给常数引用
    foo(FarmAnimal());  // 正确,将右值临时对象赋值给常数引用
    // foo(std::move(animal));  // 可选,使用移动语义将左值转换为右值
    return 0;
}

在上面的示例中,我们定义了一个FarmAnimal类,并在main函数中创建了一个左值animal。然后,我们调用foo函数两次,第一次传递了左值animal,第二次传递了右值临时对象FarmAnimal()。在foo函数中,我们使用常数引用来接受参数,这样就可以接受左值和右值的赋值。

请注意,最后一行代码是可选的,使用了std::move函数将左值animal转换为右值。这样做的目的是为了显式地表明我们要使用移动语义,将左值转移给foo函数。但是在实际应用中,需要谨慎使用std::move,确保只在需要移动语义的情况下使用。

对于腾讯云相关产品和产品介绍链接地址,由于要求不能提及具体的品牌商,我无法给出具体的链接。但是腾讯云作为一家知名的云计算服务提供商,提供了丰富的云计算产品和解决方案,包括云服务器、云数据库、云存储等。你可以通过访问腾讯云的官方网站,了解更多关于这些产品的信息和使用方式。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++11新特性学习笔记

终端:g++ xxx.cpp -std=c++11 类型推导 auto auto自动类型推导,用于初始化表达式推断出变量数据类型。...那么这个加法赋值表达式,&a是允许操作,但&(b + c)这样操作则不会通过编译。因此a是一个左,(b + c)是一个。 相对于左表示字面常量、表达式、函数引用返回等。...7.1.2 左引用引用引用是对一个左进行引用类型引用则是对一个进行引用类型。 左引用引用都是属于引用类型。...无论是声明一个左引用还是引用,都必须立即进行初始化。而其原因可以理解引用类型本身自己并不拥有所绑定对象内存,只是该对象一个别名。...,编程通过, ok “const 类型 &” “万能”引用类型,它可以接受非常量左、常量左对其进行初始化引用,使用&&表示: int && r1 = 22; int x = 5;

2.2K20

C++11新特性学习笔记

终端:g++ xxx.cpp -std=c++11 类型推导 auto auto自动类型推导,用于初始化表达式推断出变量数据类型。...那么这个加法赋值表达式,&a是允许操作,但&(b + c)这样操作则不会通过编译。因此a是一个左,(b + c)是一个。 相对于左表示字面常量、表达式、函数引用返回等。...7.1.2 左引用引用引用是对一个左进行引用类型引用则是对一个进行引用类型。 左引用引用都是属于引用类型。...无论是声明一个左引用还是引用,都必须立即进行初始化。而其原因可以理解引用类型本身自己并不拥有所绑定对象内存,只是该对象一个别名。...,编程通过, ok “const 类型 &” “万能”引用类型,它可以接受非常量左、常量左对其进行初始化引用,使用&&表示: int && r1 = 22; int x = 5;

2.1K20
  • 【Modern Cpp】万能引用到完美转发

    template void wrapper(T &u) { fun(u); } 尝试编译,报错如下: 错误:用类型‘MyClass’初始化类型‘MyClass...&’非常量引用无效 wrapper(MyClass()); 根据提示,可知发生错误代码如下: wrapper(MyClass()); 在上面的代码,MyClass()是一个,而在wrapper...确定了万能引用类型后,编译器需要推导出T&&T真实类型:若传入参数是一个左,则T会被推导引用;而如果传入参数是一个,则T会被推导原生类型引用类型)。...wrapper(MyClass()); T被推导类型MyClass(如果传入参数是一个,则T会被推导原生类型引用类型)),因此参数类型被推导MyClass&&即一个。...,有提到:若传入参数是一个左,则T会被推导引用;而如果传入参数是一个,则T会被推导原生类型引用类型),下面结合std::forward实现,我们分析下上述代码。

    48420

    CC++常见面试知识点总结附面试真题—-20220326更新

    cconst仅仅是编译层来限定,不允许对const 变量进行赋值操作,在运行期是无效,所以并非是真正常量(比如通过指针对const变量是可以修改),但是c++是有区别的,c++在编译时会把...6). c++const成员只读变量,可以通过指针修改const成员,另外const成员变量只能在初始化列表中进行初始化。 下面我们通过代码来看看区别。...,计算顺序也是往左计算,不过都是计算完以后再进行压栈操作: 对于第1个printf,首先执行++i,返回是i,这时i是2,再次执行++i,返回是i,得到i=3,将i压入栈,此时i3,...d = 10 // 正确, 常引用引用常数量是ok,其等价于 const int temp = 10; const int &d = temp 引用是 C++11 新增特性,其形式如下所示。...&&c = var // 错误,var int &&d = move(a) // ok, 通过move得到左引用 在汇编层面引用事情和常引用是相同,即产生临时量来存储常量。

    1.5K10

    《逆袭进大厂》第三弹之C++提高篇79问79答

    所有其他静态数据成员都不会被初始化。 110、抽象基类为什么不能创建对象? 抽象类是一种特殊类,它是为了抽象和设计目的建立,它处于继承层次结构较上层。...拷贝构造函数用来初始化一个引用类型对象,如果用传方式进行传参数,那么构造实参需要调用拷贝构造函数,而拷贝构造函数需要传递实参,所以会一直递归。 149、你知道空类大小是多少吗?...无论是声明一个左引用还是引用,都必须立即进行初始化。而其原因可以理解引用类型本身自己并不拥有所绑定对象内存,只是该对象一个别名。...,该临时量将会一直存活下去 特点2:引用独立于左。...int& c = 10; //错误,c是左不能使用初始化 int&& d = 10; //正确,引用初始化 int&& e = a; //错误,e是引用不能使用左初始化

    2.2K30

    C++引用

    &a = b; return 0; } (引用作为返回) Type + & + 函数名 (1)以引用返回函数值,定义函数时需要在函数名前加&; (2)用引用返回一个函数值最大好处是,在内存不产生被返回副本...} int main() { int &a = fun(); } //这是错误 并且不能成为左; 函数返回静态变量或全局变量:(这两种变量都放在全局区) 可以作为其他引用,并且可以作为左...因此上面的表达式就是试图将一个const类型对象转换为const类型,这是非法。   引用型参数应该在能被定义const情况下,尽量定义const 。...const引用const引用区别: const引用只读不可修改,与绑定对象是否const无关。...const引用可读可改,只可与const对象对象绑定; const引用只能绑定到与该引用类型对象,const引用则可以绑定到不同但相关类型对象或绑定到左; const引用可以初始化为不同类型对象或者初始化

    93540

    Chapter 5: Rvalue References, Move Semantics, PF

    通用引用引用或者左引用,可以绑定到左或者,也可以绑定到const或const对象,volatile或volatile对象上,甚至是即const又volatile对象上。...通用引用参数一般会对任何传入参数产生匹配,但是如果通用引用是包含其他通用引用参数参数列表一部分,那么在通用引用参数上不匹配会使得已经匹配通用引用参数无效。这就是标签分发基础。...编码机制是:当传递参数是一个左时,模板参数被推导引用;当传递参数是一个时,模板参数被推到一个引用。...因为存在两种引用类型(左引用引用),因此就有四种可能引用引用组合,即:指向左引用引用,指向右引用引用,指向左引用引用,指向右引用引用。...而标准规定:向函数模板传递一个花括号初始化参数,而模板参数又没有指定参数类型std::initializer_list,那么这就是一个不可推导情况。

    5.1K40

    【笔记】《深入理解C++11》(上)

    引用 ""没有严谨定义, 通常来说, 出现在等号右边内容就是, 可以取地址, 有名字就是左 不跟对象关联字面值等称为纯, 其他称为将亡 引用是为了优化对临时对象进行深拷贝效率...引用形成拷贝/赋值函数称为移动拷贝/赋值, 核心是直接窃走目标对象内部指针指向内存内容, 然后置空目标对象指针 无论声明了左引用还是引用, 都必须在声明时立即初始化(参数列和初始化列表也算立即初始化...但注意引用不能被绑定到左 引用能够延长声明周期, 常量左引用属于万能引用, 也能够延迟生命周期, 但是常量左引用不能修改所以一般用来减少临时对象开销而已 当类没有定义移动构造时...大括号初始化会制止类型窄 大括号返回是initializer_list, 可以用作函数一种重载参数 大括号也可以在return, 一般用来构造临时变量, 具体构造出来临时变量还是依靠声明返回决定...如果目标是被重载函数则编译错误 否则, 对于带括号表达式, 如果目标是将亡, 那么返回引用 对于带括号表达式, 如果目标是左, 返回左引用 否则返回目标本身类型 推导四规则中最麻烦是规则

    1.9K20

    c++入门到进阶--引用与常量

    引用 (定义 类型 &引用名=目标变量名) int a=100; int &b=a;/*&是标识符(引用必须被初始化并且初始化完成之后引用将会和初始对象一直绑定在一起)。...*/ 引用(必须要绑定到引用)定义 类型 &&引用变量=表达式; int &&a=10;//正确 int &&b=10*5;//正确10*5是 int &&c=a;//a类型是int...是左 调用标准库定义函数std::move() move()函数返回给定对象引用, 可以显式将一个左转换为对应引用类型。...返回类型和return语句 return 语句形式 return; return表达式; void函数必须返回一个与声明类型匹配否则会引起编译错误。...存储类别 static静态存储 static对象在控制流程第一次到达其定义点时被初始化,如果没有提供初始就被自动初始化为0; 在函数后续调用初始化语句被跳过 静态对象在函数被多次调用之间保持有效

    77820

    【译】理解C和C++

    不能赋给一个const引用,因为这要求一个无效到左转换。...CV限定 如果我们仔细阅读,C++ standard discussing lvalue-to-rvalue conversions【2】写道: 一个函数、数组类型T可以被转换为,...否则,这个类型是T。 cv限定是什么鬼?...cv限定和cv限定版本是两种不同类型,但它们要有相同representation(?)和对齐要求。 这和有什么联系?在C不会有cv限定符,只有左有。...通过使用复制构造函数,然后不抛出异常std::swap,确保了如果异常抛出,不会有尚未初始化内存在某个中间状态出现。 【5】现在你们知道为什么坚持把operator= 称作拷贝赋值运算符。

    1.2K10

    C++核心准则编译边学-F.19 对于只传递不处理参数,使用模板类型TP&&并在传递时使用std::forward

    如果对象不在本函数内部使用而是继续传递给其他代码,我们希望本函数不会改变参数常数特性和特性。...,首先被实参初始化,其结果是实参将无效化(引用定义)。...但是如果不是在函数体中直接使用而希望作为继续传递给另外一个函数,就不能直接使用s作为实参(因为它已经变成了左引用),而是使用forward恢复它特性。...在这种情况下,也只有在这种(引用参数只传递不使用)情况下,将TP参数定义TP&&(这里TP是模板类型)--这样可以无视并维持常量特性和特性。...TP&&类型参数本质上总是应该在函数体通过std::forward继续传递。 译者注:最终还是要被某段代码作为左使用

    1.2K00

    左右引用和移动语义

    左右和左右引用 什么是左呢?一种极不严谨理解:在赋值时候,能够被放到等号左边,放在右边。...a+a int c = sum(a, a);//c,但函数sum(a, a)返回 通过上面的例子,常数a、表达式(a+a)和函数sum(a+a)返回他们都是临时值,这些都保存在寄存器...常见有: 除字符串字面值以外字面值 返回引用类型函数调用 后置自增/减运算符链接表达式(如i++/i--) 算术/逻辑/比较表达式(如a+b,a&&b,a==b) 取地址表达式(如&a...它形式如:T&,根据const属性可以分为两种: const左引用 const左引用 例如: int a = 1; int& la = a;//laa引用const左引用) la...= 2;//laconst左引用,可以修改它 const int& c_la = a;//c_laa引用(const左引用) c_la = 2;//该语法错误,c_laconst

    87740

    C语言中常见指针问题集解答

    要自增 p 指向, 使用(*p)++, 如果副作用顺序无关紧要也可以使用 ++*p。 3. 有一个char*型指针正巧指向一些int型变量,想跳过它们。为什么如下代码不行?...((int *)p)++; 答:在 C 语言中, 类型转换意味着 “把这些二进制位看作另一种类型, 并作相应对待”; 这是一个转换操作符, 根据定义它只能生成一个 (rvalue)。...int *ip; f(ip); 答:你确定函数初始化是你希望它初始化东西吗?请记住在 C , 参数是通过传递。被调函数仅仅修改了传入指针副本。...你需要传入指针地址 (函数变成接受指针指针), 或者让函数返回指针。 5. 能否用void**指针作为参数, 使函数按引用接收一般指针? 答:不可以。C没有一般指针指针类型。...有一个函数 extern int f(int *); 它接受指向 int 型指针。怎用引用方式传入一个常数

    53740

    『C++』想学C++,C++太难了,那我想入门,给我10分钟带你入门

    返回类型和return语句 return 语句形式 return; return表达式; void函数必须返回一个与声明类型匹配否则会引起编译错误。...引用 区别 左 赋值表达式 出现在赋值号左边 在赋值号右边 地址与名字 可以取地址有名字 不能取地址没有名字 生成表达式 返回左引用函数 赋值 下标 解引用和前缀自增自减运算符...左引用 (定义 类型 &引用名=目标变量名) int a=100; int &b=a;/*&是标识符(引用必须被初始化并且初始化完成之后引用将会和初始对象一直绑定在一起)。...*/ 引用(必须要绑定到引用)定义 类型 &&引用变量=表达式; int &&a=10;//正确 int &&b=10*5;//正确10*5是 int &&c=a;//a类型是...int是左 调用标准库定义函数std::move() move()函数返回给定对象引用, 可以显式将一个左转换为对应引用类型

    1.6K10

    const 详解

    ;  //合法    2、 必须初始化    const int i=5;    //合法    const int j;      //非法,导致编译错误    3、在另一连接文件引用const...,以致在以后代码没有错误达到说教效果,特别地用&i明确地给出了i内存分配。...6、可以通过函数对常量进行初始化    int value();    const int i=value();    dapingguo说:假定对ROM编写程序时,由于目标代码不可改写,本语句将会无效...; //指针p3i是常量,所指内容也是常量    p1i=&ii;                  //合法    *p2i=100;                //合法    在好长一段时间被...以下程序,类stack成员函数GetCount仅用于计数,逻辑上讲GetCount应当const函数。编译器将指出GetCount函数错误

    1K10

    初识C++ · C++11(1)

    C++11委员会扩大了列表初始化范围,标准库里面的vector等stl容器到用户自定义类型或者是内置类型都可以这么初始化了,所以一个整型,一个数组可以初始化方式就有很多种了: int main(...2.3 nullptr 在C++,对于NULL定义一直是宏定义0,这就可能引入部分问题了,因为同时可以表示整型和指针类型,C++11出于安全考虑加入了nullptr,表示空指针。...这里可以总结一下,纯就是内置类型或字面量值,将亡就是自定义类型。 提问,左能给引用吗?...那么为什么引入呢?左引用短板是什么?...为什么打引号呢?因为主函数str占用了Func里面的str指向空间,之后Func::str就销毁了,就像是一种器官移植,将str空间继续延续下去,这就是引用恐怖之处。

    6910

    【C++】C++11常用特性总结

    知道上面的知识后,也就能解释为什么移动构造或移动赋值或引用版本插入等等接口参数都是普通引用了,因为这些接口都要对进行资源移动,也就是改变引用引用对象,所以右引用时候必须是普通引用...,所以可以看到push_back,insert,list_node等函数在传递引用实体时,都需要加move保持其属性依旧,这样才能在层层调用过程引用实体一直保持。...&&这样引用方式我们都知道他是引用,但&&在模板并不代表引用,他有新名词,叫做万能引用,所谓万能引用就是什么类型参数都可以接收,包括普通左,普通,const左,const,万能引用都可以接收...推演实例化时候,也会由于参数不同相应实例化出不同函数实体,如果传过来是左,&&在接收时候,会发生引用折叠,也就是由两个&变为一个&,形式上引用折叠引用。 3....其实还有一种方法,就是只声明不实现,这样就会报链接错误,因为编译阶段生成符号表存拷贝构造函数地址是无效,所以链接阶段通过地址找拷贝构造函数定义时,就会发生链接错误,所以这样方式也可以防拷贝。

    81140

    【C++进阶】C++11认识与学习

    一.列表初始化 这个要和构造函数初始化列表区分开。 在C++11,新增加了列表初始化,即可以用(=){},给所有的内置类型和自定义类型初始化(等号可有可无)。...过(注意,a仍然是左,只不过是move返回是一个) //注意 rr1 rr2 属性仍 return 0; } 引用应用 场景1 自定义类型深拷贝,必须传返回场景...str 是一个左,并不是为什么会调用移动赋值呢?...四.完美转发  模板&& 万能引用 当 && 写在模板,它就是万能引用,既可以是左引用,也可以是引用。...这可以确保派生类函数正确地重写了基类虚函数,并且可以避免一些程序错误

    15910

    C++为什么会有这么多难搞类别

    (话说可能自然语言都不见得有这么复杂吧……),那么这篇我们就来详细研究一下,为什么要专门定义这样类型,以及在这个过程笔者自己思考。...那么也就是说,在早版本C++,对于用变量接收平凡类型返回时,按xvalue处理。...而为了解决这个问题,C++引入了「引用」。其实这个语法完完全全就是为了解决函数返回问题,但为什么叫「引用」呢?...那么结论也就呼之欲出了:引用语义上来说,是对引用,但一旦完成了这种引用,其实整个过程就不会出现值了,而是用一个左来保存返回,这就是我们为什么一直强调说「引用本身是左」了。...所以这里语义上来说函数返回是rvalue,包括常数也是一种rvalue,所以右引用做函数参数时,用于「接收」一个rvalue。那么这里更加强调是语义上「接收」,这里希望接收一个

    1.1K52

    Swift基础 基础知识

    这些被称为常数,比C常数强大得多。在整个 Swift ,常量会使用,使代码在处理不需要更改时更加安全、更清晰。...这种选择加入方法可以防止隐藏转换错误,并有助于在代码明确类型转换意图。 要将一种特定数字类型转换为另一种特定数字类型,请使用现有初始化所需类型新数字。...在幕后,UInt16有一个接受UInt8初始化器,因此此初始化器用于现有的UInt8制作新UInt16。然而,您不能在这里传递任何类型——它必须是UInt16提供初始化类型。...它可以被描述类型元组(Int,String)”。 您可以任何类型排列创建元组,它们可以包含任意数量不同类型。...在这些情况下,每次访问可选时,无需检查和打开其,因为可以安全地假设它一直具有。 这些类型可选选项被定义隐式未包装可选选项。您通过放置感叹号(String!)

    15400
    领券