- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经问了几个涉及这个问题的问题,但我得到了不同的回答,所以我认为最好直接问。
假设我们有以下代码:
// Silly examples of A and B, don't take so seriously,
// just keep in mind they're big and not dynamically allocated.
struct A { int x[1000]; A() { for (int i = 0; i != 1000; ++i) { x[i] = i * 2; } };
struct B { int y[1000]; B() { for (int i = 0; i != 1000; ++i) { y[i] = i * 3; } };
struct C
{
A a;
B b;
};
A create_a() { return A(); }
B create_b() { return B(); }
C create_c(A&& a, B&& b)
{
C c;
c.a = std::move(a);
c.b = std::move(b);
return C;
};
int main()
{
C x = create_c(create_a(), create_b());
}
现在理想情况下 create_c(A&&, B&&)
应该是空操作。调用约定不是创建 A 和 B 并在堆栈上传递对它们的引用,而是应该创建 A 和 B 并按值传递,以代替返回值 c
。对于 NRVO,这意味着创建它们并将它们直接传递到 x
,而无需函数 create_c
做进一步的工作。
这将避免创建 A 和 B 的拷贝的需要。
是否有任何方法可以允许/鼓励/强制编译器执行此行为,或者优化编译器通常会这样做吗?这仅在编译器内联函数时有效,还是跨编译单元有效。
(我认为这如何跨编译单元工作...)
如果 create_a()
和 create_b()
接受了一个隐藏的参数,即返回值的放置位置,它们可以将结果放入 x
直接,然后通过引用传递给 create_c()
,后者什么都不用做并立即返回。
最佳答案
有多种优化代码的方法,但右值引用不是一种。问题是 A
和 B
都不能免费移动,因为你不能窃取物体。考虑以下示例:
template <typename T>
class simple_vector {
typedef T element_type;
typedef element_type* pointer_type;
pointer_type first, last, end_storage;
public:
simple_vector() : first(), last(), end_storage() {}
simple_vector( simple_vector const & rhs ) // not production ready, memory can leak from here!
: first( new element_type[ rhs.last - rhs.first ] ),
last( first + rhs.last-rhs.first ),
end_storage( last )
{
std::copy( rhs.first, rhs.last, first );
}
simple_vector( simple_vector && rhs ) // we can move!
: first( rhs.first ), last( rhs.last ), end_storage( rhs.end_storage )
{
rhs.first = rhs.last = rhs.end_storage = 0;
}
~simple_vector() {
delete [] rhs.first;
}
// rest of operations
};
在这个例子中,由于资源是通过指针保存的,所以有一种简单的方法可以移动对象(即将旧对象的内容窃取到新对象中,并将旧对象留在一个可销毁但无用的状态。只需复制指针并将它们在旧对象中重置为 null,这样原始对象析构函数就不会释放内存。
A
和 B
的问题在于,实际内存是通过数组保存在对象中的,而该数组不能移动到新的 C
对象的不同内存位置。
当然,由于您在代码中使用堆栈分配的对象,编译器可以使用旧的 (N)RVO,当您这样做时:C c = { create_a(), create_b() } ;
编译器可以执行该优化(基本上是在从 create_a
返回的对象的地址上设置属性 c.a
,而在编译 create_a
,直接在同一地址上创建返回的临时对象,因此有效地 c.a
,从 create_a
返回的对象和 create_a
中构造的临时对象(隐含 this
到构造函数)是相同的对象,避免了两次复制。同样可以用 c.b
完成,避免了复制成本。如果编译器确实内联您的代码,它将删除 create_c
并将其替换为类似于以下内容的结构:C c = {create_a(), create_b()};
所以它可以优化所有拷贝。
另一方面请注意,这种优化不能完全用于 C
对象动态分配的情况,如 C* p = new C; p->a = create_a();
,由于目的地不在栈中,编译器只能优化create_a
里面的temporary及其返回值, 但它不能使它与 p->a
重合,因此需要进行复制。这是 rvalue-references 相对于 (N)RVO 的优势,但如前所述,您不能直接在代码示例中有效地使用 rvalue-references。
关于c++ - 可以优化从临时对象创建复合对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5865899/
我正在实现一个显示容器级别的图表。根据填充水平,线条的颜色应该改变(例如,接近最大值时应该显示红色)。我不想计算线条的不同部分并手动设置它们的颜色,而是想定义一个颜色自动改变的带。我想用自定义 Com
#include int main(void) { int days, hours, mins; float a, b, c, total, temp, tempA, tempB; a
if()//first if { if()//second if statement; } else statement; 我知道 else 与第一个 if 匹配,但我的问题是为什么?我是
以下代码中测试了 Ready 的哪个实例,为什么? interface type TObject1 = class ... public property Ready: boole
我刚刚花了相当多的时间来寻找像这个 plunk 中的差距.问题没那么简单。这是一个动态创建的页面,一些具有 margin-bottom 的组件恰好显示在 .main 的最后。 在我指责 CSS 之前,
我的程序应该在对话中创建圆形图标。我有三个按钮,每个按钮代表要制作的图标的颜色。因此,如果我点击不同的按钮 10 次,我的程序应该创建 10 个不同颜色的圆圈。这是我的代码,分为 2 个类: impo
我读过; A compound literal is a C99 feature that can be used to create an array with no name. Consider
当您创建一个复合 View 并为其扩充 xml 布局文件时,如下所示: public class CompundLayout extends LinearLayout{...} 这会像这样用根扩展一个
我正在创建一个带有标签和文本框的复合 uibinder 小部件。 预期用途是: The text to be put in the box. 我找到了如何使用自定义 @UiConstruc
任何人都可以举一个结合使用设计模式组合和责任链的实际例子吗? 谢谢 最佳答案 一个非常实际的例子是 GUI 设计,例如 Qt 框架。 QObject 可以是单个对象或多个对象的组合。 QObjects
我在这个项目中的一些表单中使用了复合 View 模型的模式。它工作得很好。 在这种情况下,我有一个 VendorAddress View 模型。我在这个项目的几个地方使用了 Address(es),所
我正在尝试构建一个我认为需要多个 JOIN 的 SQL 查询,但我不知道语法。 这是每个表(带有列名)的粗略示例。 T1( key ,名称) T2(键,fkeyT1) T3(键,fkeyT2) 我想从
我有一个 Composite我希望能够以编程方式启用/禁用。 Control.setEnabled(boolean enabled)方法工作正常,但它没有提供任何小部件被禁用的视觉信息。 我想做的是让
如果子域不是“mobile”并且文件名不是“design”或“photo”,我想回显某些内容,因此 echo if (not“mobile”且不是“design”)或(not“mobile”而不是“照
我有一张有几列的 table 。第 1 列和第 2 列可以包含四个 alpha 值中的任何一个:set={A,B,C,D}。 我想检查每列是否包含集合中的两个值之一。所以我想简化这个陈述: SELEC
我创建了一个全局数据类型,并在页面中使用表单渲染器让用户填写数据并提交到网站。 默认的英语工作正常。现在,当我尝试支持第二种语言时,我遇到了问题。根据复合文档: 1.在 ~/Frontend/Comp
我需要将自定义对象作为值存储在字典中,例如具有两个复合整数键的 datastrukturer。 (复合 ID) 我尝试使用数组作为键,但两者都不起作用,因为我猜这只是指向该数组的指针,用作键 如果我能
版本:3.2.1 关系 表B中的两列与表A中的两列相关联。 表A-> hasMany->表B 表B->属于--表A B.a_id = A.a_id B.a_name = A.a_name 食谱 在食谱
我创建了一个全局数据类型,并在页面中使用表单渲染器让用户填写数据并提交到网站。 默认的英语工作正常。现在,当我尝试支持第二种语言时,我遇到了问题。根据复合文档: 1.在 ~/Frontend/Comp
当前版本的 Log4net 是否有办法创建具有复合滚动样式的 RollingFileAppender,其中滚动文件始终保留给定的扩展名(在我的情况下为 .log)? 我想要的格式示例: MyLog.l
我是一名优秀的程序员,十分优秀!