是右值引用定义行为的直接实例化
Is direct instantiation of an rvalue reference defined behavior?
以下代码使用 g++ 6.3.0 和 -Wall 进行干净编译。
#include <iostream>
class Base
{
public:
Base(char const* base) : base_(base) {}
void print( char const* msg ) { print( base_, msg ); }
protected:
~Base() = default;
private:
char const* base_;
virtual void print( char const*, char const* ) = 0;
};
class Drv1 : public Base
{
public:
Drv1(char const* base, int i) : Base(base) , i_(i) {}
~Drv1() { std::cout << "Drv1 dtor" << std::endl; }
private:
int i_;
void print( char const* base, char const* msg ) override
{
std::cout << base << "(" << msg << "): " << i_ << std::endl;
}
};
class Drv2 : public Base
{
public:
Drv2(char const* base, double d) : Base(base) , d_(d) {}
~Drv2() { std::cout << "Drv2 dtor" << std::endl; }
private:
double d_;
void print( char const* base, char const* msg ) override
{
std::cout << base << "(" << msg << "): " << d_ << std::endl;
}
};
void do_test( char const* base, char const* msg, bool int_type )
{
Base&& _base(int_type ? (Base&&)Drv1(base, 1) : (Base&&)Drv2(base, 2.5));
_base.print( msg );
}
int main()
{
do_test( "Test1", "int", true );
do_test( "Test2", "double", false );
return 0;
}
运行时,输出如下:
Drv1 dtor
Test1(int): 1
Drv2 dtor
Test2(double): 2.5
问题:
如果在调用虚函数之前调用了派生类析构函数,如何定义此行为?如果输出实际上只是一个幸运的意外,那么编译器选项是什么来捕获此问题?
rvalue reference
是do_test()
中局部变量_base
类型的正确术语吗? 通用(或转发(引用发生在模板的上下文中,但此处没有模板。
通过将引用绑定到临时的生存期延长,对于右值引用的规则与对左值引用的规则相同 - 除了非常量右值引用可以绑定到临时引用,而非常量右值引用不能。
该程序确实有 UB。在此表达式中:(Base&&)Drv2(base, 2.5)
构造一个临时对象,并绑定一个引用。接下来,该引用用于初始化完整表达式 Base&& _base(int_type ? (Base&&)Drv1(base, 1) : (Base&&)Drv2(base, 2.5));
中的另一个引用。临时引用的临时引用的生存期不会延长_base
的生存期。因此,引用悬而未决。以后访问该值具有未定义的行为。
仅当使用创建临时的表达式直接初始化引用时,才可以延长临时的生存期。例如:
Base&& _base(Drv2(base, 2.5));
相关文章:
- 对显式实例化的模板函数的未定义引用
- 为什么我不能引用指向实例化对象的函数的指针?
- 请参阅在 Visual Studio 2019 中捕获 std::exception 时对函数模板实例化消息的引用
- 引用的静态强制转换强制模板实例化,其中不完整的类型很好
- 为什么不能在实例化对基类的引用的同时实例化指向派生类的指针?
- 非类型引用参数可以在运行时修改,这是否意味着模板可以在运行时实例化?
- 反向函数不反转类实例化的引用字符串
- 类模板实例化和通用引用
- 对由文本实例化的对象的类引用
- 如何使用引用类型实例化模板函数
- 共享库:具有部分模板专用化和显式模板实例化的未定义引用
- 是右值引用定义行为的直接实例化
- 为构造函数初始化引用实例变量提供默认值
- 显式模板实例化和转发引用
- 为什么不能将继承自(非模板)类 B 的实例化类模板 A 的引用转换为对 B 的引用?
- 由类中未实例化的静态成员变量引起的未定义引用C++
- 如何实例化C++成员字符串引用
- 强制 clang 为类模板实例化的从不引用的静态成员函数发出代码
- 从类代码内部使用对对象实例化的引用
- 类实例化时未定义的引用错误