我希望在C++20中,下面的代码在打印A和B之间不打印任何内容(因为我希望保证RVO会起作用)。但输出为:
a
拜拜
b
c
拜拜
拜拜
所以大概是创建了一个临时的。
#include<iostream>
#include<tuple>
struct INeedElision{
int i;
~INeedElision(){
std::cout << "Bye\n";
}
};
std::tuple<int, INeedElision> f(){
int i = 47;
return {i, {47}};
}
INeedElision g(){
return {};
}
int main()
{
std::cout << "A\n";
auto x = f();
std::cout << "B\n";
auto y = g();
std::cout << "C\n";
}
这种行为的原因是什么?是否有避免复制(不使用指针)的变通方法?
https://godbolt.org/z/zasogd
只有返回对象本身时,才会获得复制选择:
std::vector<int> fn1()
{
return std::vector<int>{}; // guaranteed copy elision
}
std::vector<int> fn2()
{
std::vector<int> vec;
return vec; // a good compiler will manage to elide the copy/move here
}
在您的示例中,您返回的是tuple,因此tuple本身可能被复制省略,但传递给tuple构造函数的参数却不被复制省略!
std::tuple<int, INeedElision> f(){
int i = 47;
return {i, {47}}; // construct the tuple in place of the return address but the arguments are copied into the tuple and not even moved ! to move call std::move explicitly
}
编译器不允许删除传递给元组构造函数的参数副本,因为您返回的不是参数本身,而是包含这些参数副本的元组。还要注意,表不能保存对参数的引用,因为这些局部变量在函数返回时已经被销毁,从而产生悬空引用。
如果您想在C++17中获得一个复制省略的机会,并在以后做一些类似的事情:
std::tuple<int, INeedElision> f(){
std::tuple<int, INeedElision> ret;
auto& [i, ne] = ret;
i = 47;
ne = 47;
return ret;
}
从{i,{47}}
构造std::tuple
时,std::tuple
的选定构造函数通过对const
的lvalue-reference获取元素。
tuple( const Types&... args );
然后,当使用{i,{47}}
作为初始值设定项时,将构造一个临时的ineDelision
,然后传递给std::tuple
的构造函数(并得到复制)。临时对象将立即被销毁,您将看到“a”和“b”之间的“bye”。
BTW:std::tuple
的第三个构造函数不会用于这种情况。
template< class... UTypes >
tuple( UTypes&&... args );
它是一个构造函数模板,像{47}
这样的括号-init-list没有类型,不能通过模板参数推导来推导。
另一方面,如果ineDelision
有一个转换构造函数,它取int
,并使初始值设定项为{i,47}
,则将使用std::tuple
的第三个构造函数,而不构造临时的ineDelision
;该元素将从int
47
就地构造。
活着
我需要在Go中复制一个切片,并读取文档。有一个复制功能可供我使用。 copy内置函数将元素从源片复制到目标片。(作为一种特殊情况,它还会将字节从字符串复制到字节片。)源和目标可能重叠。Copy返回复制的元素数,它是len(src)和len(dst)中的最小值。 但当我这样做的时候: 我的和以前一样是空的(我甚至尝试使用): 你可以去游乐场看看。那么为什么我不能复制一个切片呢?
问题内容: 从JavaDoc: 验证此容器及其所有子组件。验证容器意味着布置其子组件。 那就是我想做的。使用尽可能轻巧的组件。但是当我这样做时,对的调用不会使组件“有效”。 为什么我不能做一个有效的? 问题答案: 在文档中说: 当组件在其父容器中的大小和位置正确且其所有子组件也均有效时,该组件才有效。 这种情况,直到你达到顶级容器(,或)。在您所遇到的问题的示例中,您没有父母,所以它永远不会有效。
下面是一个多态字段: 其中是接口,是结构/类中其他位置的字段。 在这种情况下我怎么会有这种行为呢?
问题内容: 我有一个div,在该div内,我有一个无序列表。我已将其应用于无序列表,但不会在标头div中居中。 有人可以告诉我为什么吗?我认为,如果我定义父div的宽度,那么无序列表应该能够以居中。我想念什么? 这是我的代码: 问题答案: 您需要定义要居中的元素的宽度,而不是父元素。 编辑 :好的,我现在已经看到了测试页,这就是我认为您想要的:
主要内容:可见性,原子性,举个例子首先要了解的是,volatile可以保证可见性和顺序性,这些都很好理解,那么它为什么不能保证原子性呢? 可见性 可见性与Java的内存模型有关,模型采用缓存与主存的方式对变量进行操作,也就是说,每个线程都有自己的缓存空间,对变量的操作都是在缓存中进行的,之后再将修改后的值返回到主存中,这就带来了问题,有可能一个线程在将共享变量修改后,还没有来的及将缓存中的变量返回给主存中,另外一个线程就对共享变量
主要内容:可见性,原子性,举个例子首先要了解的是,volatile可以保证可见性和顺序性,这些都很好理解,那么它为什么不能保证原子性呢? 可见性 可见性与Java的内存模型有关,模型采用缓存与主存的方式对变量进行操作,也就是说,每个线程都有自己的缓存空间,对变量的操作都是在缓存中进行的,之后再将修改后的值返回到主存中,这就带来了问题,有可能一个线程在将共享变量修改后,还没有来的及将缓存中的变量返回给主存中,另外一个线程就对共享变量
问题内容: 我需要在Go中制作切片的副本,并阅读文档,这里有一个复制功能供我使用。 内置复制功能将元素从源切片复制到目标切片。(在特殊情况下,它还会将字节从字符串复制到字节切片。)源和目标可能会重叠。复制返回复制的元素数量,该数量将是len(src)和len(dst)的最小值。 但是当我这样做时: 与以前一样,我是空的(甚至尝试使用): 您可以在运动场上查看。那为什么不能复制切片? 问题答案: 内
我有自己的目录结构: 在我的Dockerfile中,我将复制到目录,但不幸的是,它没有被复制: 错误: