引用的临时对象的析构函数
Destructor of referenced temporary object
举个例子:
#include <iostream>
#include <cstdlib>
#define PRINT_NAME { std::cout << __PRETTY_FUNCTION__ << std::endl; }
namespace
{
struct A
{
A() { PRINT_NAME; }
~A() { PRINT_NAME; }
};
A f() { return {}; }
A b;
A && g() { return std::move(b); }
}
int
main()
{
std::cout << "------------------" << std::endl;
{
f();
std::cout << 1 << std::endl;
}
std::cout << "------------------" << std::endl;
{
A && a = f();
// or A const & a = f(); as mentioned in below discussion
std::cout << 2 << std::endl;
}
std::cout << "------------------" << std::endl;
{
A && a = g();
std::cout << 3 << std::endl;
}
std::cout << "------------------" << std::endl;
return EXIT_SUCCESS;
}
及其输出(clang 3.5.0):
(anonymous namespace)::A::A()
------------------
(anonymous namespace)::A::A()
(anonymous namespace)::A::~A()
1
------------------
(anonymous namespace)::A::A()
2
(anonymous namespace)::A::~A()
------------------
3
------------------
(anonymous namespace)::A::~A()
什么是语义规则:标准段落的一个可思考的缩写,它简洁地总结了上述代码示例的析构函数行为的差异?我经常面对通过 "have some (non-obviously relevant) characteristic" 或 "have some inherent attribute" 语句制定的 "idiomatic rules",例如"if it has a name, then it is an lvalue"。有类似的吗?
这与右值引用无关。事实上,如果在整个代码中将 A&&
更改为 const A&
,则 the behavior won't change.
可能您的困惑是由 std::move()
函数的名称引起的。它实际上并没有移动任何东西,它只是将其参数转换为右值引用。
不要考虑析构函数,考虑对象的生命周期。我个人不知道简单的经验法则("read the standard" 除外),但这三个规则可能对您有所帮助:
- 静态对象具有(基本上)整个程序的生命周期。
- 如果从函数返回的临时对象未绑定到任何对象,则它的生命周期在整个表达式执行完成时结束。
- 如果从函数返回的临时对象绑定到某个引用,则其生命周期会延长到该引用的生命周期。
举个例子:
#include <iostream>
#include <cstdlib>
#define PRINT_NAME { std::cout << __PRETTY_FUNCTION__ << std::endl; }
namespace
{
struct A
{
A() { PRINT_NAME; }
~A() { PRINT_NAME; }
};
A f() { return {}; }
A b;
A && g() { return std::move(b); }
}
int
main()
{
std::cout << "------------------" << std::endl;
{
f();
std::cout << 1 << std::endl;
}
std::cout << "------------------" << std::endl;
{
A && a = f();
// or A const & a = f(); as mentioned in below discussion
std::cout << 2 << std::endl;
}
std::cout << "------------------" << std::endl;
{
A && a = g();
std::cout << 3 << std::endl;
}
std::cout << "------------------" << std::endl;
return EXIT_SUCCESS;
}
及其输出(clang 3.5.0):
(anonymous namespace)::A::A()
------------------
(anonymous namespace)::A::A()
(anonymous namespace)::A::~A()
1
------------------
(anonymous namespace)::A::A()
2
(anonymous namespace)::A::~A()
------------------
3
------------------
(anonymous namespace)::A::~A()
什么是语义规则:标准段落的一个可思考的缩写,它简洁地总结了上述代码示例的析构函数行为的差异?我经常面对通过 "have some (non-obviously relevant) characteristic" 或 "have some inherent attribute" 语句制定的 "idiomatic rules",例如"if it has a name, then it is an lvalue"。有类似的吗?
这与右值引用无关。事实上,如果在整个代码中将 A&&
更改为 const A&
,则 the behavior won't change.
可能您的困惑是由 std::move()
函数的名称引起的。它实际上并没有移动任何东西,它只是将其参数转换为右值引用。
不要考虑析构函数,考虑对象的生命周期。我个人不知道简单的经验法则("read the standard" 除外),但这三个规则可能对您有所帮助:
- 静态对象具有(基本上)整个程序的生命周期。
- 如果从函数返回的临时对象未绑定到任何对象,则它的生命周期在整个表达式执行完成时结束。
- 如果从函数返回的临时对象绑定到某个引用,则其生命周期会延长到该引用的生命周期。