- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
鉴于此代码示例,关于传递给 S
的临时字符串的生命周期的规则是什么。
struct S
{
// [1] S(const std::string& str) : str_{str} {}
// [2] S(S&& other) : str_{std::move(other).str} {}
const std::string& str_;
};
S a{"foo"}; // direct-initialization
auto b = S{"bar"}; // copy-initialization with rvalue
std::string foobar{"foobar"};
auto c = S{foobar}; // copy-initialization with lvalue
const std::string& baz = "baz";
auto d = S{baz}; // copy-initialization with lvalue-ref to temporary
按照标准:
N4140 12.2 p5.1(在 N4296 中删除)
A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
N4296 12.6.2 p8
A temporary expression bound to a reference member in a mem-initializer is ill-formed.
因此,像 [1]
这样的用户定义构造函数绝对不是我们想要的。在最新的 C++14 中,它甚至应该是格式错误的(或者是吗?)gcc 和 clang 都没有警告过它。
它会随着直接聚合初始化而改变吗?我看起来在那种情况下,临时生命周期延长了。
现在关于复制初始化,Default move constructor and reference members声明 [2]
是隐式生成的。鉴于移动可能会被省略,同样的规则是否适用于隐式生成的移动构造函数?
a、b、c、d
中哪一个具有有效引用?
最佳答案
除非有特定的异常(exception),否则绑定(bind)到引用的临时对象的生命周期会延长。也就是说,如果没有这个异常,那么生命周期就会被延长。
来自最近的草稿,N4567:
The second context [where the lifetime is extended] is when areference is bound to a temporary. The temporary to which thereference is bound or the temporary that is the complete object of asubobject to which the reference is bound persists for the lifetime ofthe reference except:
- (5.1) A temporary object bound to a reference parameter in a function call (5.2.2) persists until the completion of thefull-expression containing the call.
- (5.2) The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary isdestroyed at the end of the full-expression in the return statement.
- (5.3) A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expressioncontaining the new-initializer.
正如 OP 所述,C++11 的唯一重大变化是,在 C++11 中,引用类型的数据成员有一个额外的异常(exception)(来自 N3337):
- A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
这已在 CWG 1696(C++14 后)中删除,现在通过 mem-initializer 将临时对象绑定(bind)到引用数据成员的格式不正确。
关于 OP 中的示例:
struct S
{
const std::string& str_;
};
S a{"foo"}; // direct-initialization
这会创建一个临时的 std::string
并用它初始化 str_
数据成员。 S a{"foo"}
使用聚合初始化,因此不涉及 mem-initializer。没有适用于生命周期延长的异常(exception),因此该临时的生命周期被延长到引用数据成员 str_
的生命周期。
auto b = S{"bar"}; // copy-initialization with rvalue
在使用 C++17 强制复制省略之前:形式上,我们创建一个临时 std::string
,通过将临时 std::string
绑定(bind)到 str_ 来初始化一个临时
引用成员。然后,我们将该临时 S
S
移动到 b
中。这将“复制”引用,这不会延长 std::string
临时文件的生命周期。但是,实现会省略从临时 S
到 b
的移动。但是,这一定不会影响临时 std::string
的生命周期。您可以在以下程序中观察到这一点:
#include <iostream>
#define PRINT_FUNC() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
struct loud
{
loud() PRINT_FUNC()
loud(loud const&) PRINT_FUNC()
loud(loud&&) PRINT_FUNC()
~loud() PRINT_FUNC()
};
struct aggr
{
loud const& l;
~aggr() PRINT_FUNC()
};
int main() {
auto x = aggr{loud{}};
std::cout << "end of main\n";
(void)x;
}
请注意,loud
的析构函数在“main 结束”之前调用,而 x
一直存在到该跟踪之后。正式地,临时 loud
在创建它的完整表达式结束时被销毁。
如果 aggr
的移动构造函数是用户定义的,则行为不会改变。
在 C++17 中强制复制省略:我们将 rhs S{"bar"}
上的对象与 lhs 上的对象识别b
。这会导致临时文件的生命周期延长到 b
的生命周期。见 CWG 1697 。
对于其余两个示例,移动构造函数(如果调用)只是复制引用。当然,可以省略移动构造函数(S
),但这不是可观察的,因为它只复制引用。
关于c++ - 聚合引用成员和临时生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35313292/
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
我正在尝试将 JSON 发送到我的服务器并作为结果检索 JSON。例如发送用户名和密码并取回 token 和其他内容。 这就是我正在为发送的 HTTP 请求所做的。我现在如何检索同一请求中的内容?
我有以下 xts 矩阵: > options(digits.secs = 6) > set.seed(1234) > xts(1:10, as.POSIXlt(1366039619, tz="EST"
我目前正在开发一个应用程序,当用户到达某个位置时,它会提醒用户。我希望这个应用程序也在后台运行并搜索解决方案。 在 AppStore 中,我发现了一款名为“Sleep Cycle”的应用程序,它可
我想创建一个基于 farbtastic color picker 的颜色选择器。我想要实现的是添加我想要链接到色轮的 RGB slider 。这是我到目前为止所拥有的。 app.controller(
RFC 5545 允许 RDATE 属性具有 PERIOD 数据类型。该数据类型的语义是什么?据我所知,这是未指定的。它会改变事件的持续时间吗?如果时区更改且没有持续时间怎么办? 最佳答案 尽管我
在 CodinGame学习平台,C# 教程中用作示例的问题之一是: The aim of this exercise is to check the presence of a number in a
我听说网上有一本英特尔书,它描述了特定汇编指令所需的 CPU 周期,但我找不到(经过努力)。谁能告诉我如何找到CPU周期? 这是一个例子,在下面的代码中,mov/lock 是 1 个 CPU 周期,x
据我所知,Java GC有次要GC(低成本)和主要GC周期(高成本)。如果对象在本地范围内,则会在 Minor GC 中清理它。如果对象的引用存储在代码中的其他位置,则它会在主 GC 中被清除。 例如
到目前为止,我有一个很好的自旋锁,可以用作 intendend: std::atomic_flag barrier = ATOMIC_FLAG_INIT; inline void lo
晚上好,我将 cycle2 与 prev 和 next 函数一起使用,但我无法将 prev 和 next 函数置于图像下方的中心。我环顾四周,我知道这会很愚蠢,但我就是看不到它。非常令人沮丧。谢谢加里
出于教育目的,我想知道在优化(在不同级别)和编译之后执行函数需要多少 CPU 周期。有没有办法分析代码或可执行文件以获得可重现的答案?我在 64 位 Windows 7 Pro 上使用 Eclipse
我想彻底测量和调整我的 C/C++ 代码,以便在 x86_64 系统上更好地使用缓存。我知道如何使用计数器(我的 Windows 机器上的 QueryPerformanceCounter)来测量时间,
我尝试将一些数据分组到每四周一次的存储桶中,并使用 pd.Grouper(key='created_at', freq='4W')。我希望这些组是这样的,如果我有从 2019-08-26 到 2019
我正在做一个关于随机数的大型学校项目,但我找不到 Math.random() 的句点。我安装了 7.0.800.15 版本,并且正在使用 Windows 10 计算机。我试过用一个简单的程序来确定周期
我正在努力解决我们生产环境中垃圾收集利用率高的问题,我想知道设置一个大的堆大小来保证老年代永远不会被填满是否会阻止触发主要的 GC 周期。 为了实现这一点,我想有一个特定的阈值标记会触发主要的 GC
我想测量在 Python 3 中执行加法运算所需的时钟周期数。 我写了一个程序来计算加法运算的平均值: from timeit import timeit def test(n): for i
我正在寻找一种方法来测量线程上的函数调用所花费的 cpu 周期。 示例伪代码: void HostFunction() { var startTick = CurrentThread.Cur
就 CPU 周期而言,malloc() 的成本是多少?(Vista/OS,最新版本的 gcc,最高优化级别,...) 基本上,我正在实现一个复杂的 DAG 结构(类似于链表)由一些 16B(不太常见)
C/C++ 中的类型转换会导致额外的 CPU 周期吗? 我的理解是,至少在某些情况下应该消耗额外的 CPU 周期。就像从浮点类型转换为整数一样,CPU 需要将浮点结构转换为整数。 float a=2.
我是一名优秀的程序员,十分优秀!