- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这里有很多关于何时可以完成 RVO 的讨论,但关于何时真正完成的讨论并不多。正如多次声明的那样,RVO 不能根据标准得到保证,但是有没有办法保证 RVO 优化成功或相应代码编译失败?
到目前为止,我部分成功地在 RVO 失败时使代码发出链接错误。为此,我声明了复制构造函数而不定义它们。显然,在我需要实现一个或两个复制构造函数(即 x(x&&)
和 x(x const&)
)的极少数情况下,这显然既不稳健也不可行。
这引出了我的第二个问题:为什么编译器编写者选择在用户定义的复制构造函数就位时启用 RVO,而不是在仅存在默认复制构造函数时选择启用 RVO?
第三个问题:是否有其他方法可以为普通数据结构启用 RVO?
最后一个问题( promise ):你知道有什么编译器可以让我的测试代码表现得与我用 gcc 和 clang 观察到的不同吗?
这是 gcc 4.6、gcc 4.8 和 clang 3.3 的一些示例代码,显示了问题。该行为不依赖于一般优化或调试设置。当然选项 --no-elide-constructors
会按照它说的去做,即关闭 RVO。
#include <iostream>
using namespace std;
struct x
{
x () { cout << "original x address" << this << endl; }
};
x make_x ()
{
return x();
}
struct y
{
y () { cout << "original y address" << this << endl; }
// Any of the next two constructors will enable RVO even if only
// declared but not defined. Default constructors will not do!
y(y const & rhs);
y(y && rhs);
};
y make_y ()
{
return y();
}
int main ()
{
auto x1 = make_x();
cout << "copy of x address" << &x1 << endl;
auto y1 = make_y();
cout << "copy of y address" << &y1 << endl;
}
输出:
original x address0x7fff8ef01dff
copy of x address0x7fff8ef01e2e
original y address0x7fff8ef01e2f
copy of y address0x7fff8ef01e2f
RVO 似乎也不适用于纯数据结构:
#include <iostream>
using namespace std;
struct x
{
int a;
};
x make_x ()
{
x tmp;
cout << "original x address" << &tmp << endl;
return tmp;
}
int main ()
{
auto x1 = make_x();
cout << "copy of x address" << &x1 << endl;
}
输出:
original x address0x7fffe7bb2320
copy of x address0x7fffe7bb2350
更新:请注意,某些优化很容易与 RVO 混淆。像 make_x
这样的构造函数助手就是一个例子。参见 this example优化实际上是由标准强制执行的。
最佳答案
问题是编译器做了太多的优化:)
首先,我禁用了make_x()
的内联,否则我们无法区分RVO和内联。但是,我确实将其余部分放入匿名 namespace ,以便外部链接不会干扰任何其他编译器优化。 (证据表明,外部链接可以防止内联,谁知道还有什么......)我重写了输入输出,现在它使用 printf()
;否则生成的汇编代码会因为所有 iostream
的东西而变得困惑。所以代码:
#include <cstdio>
using namespace std;
namespace {
struct x {
//int dummy[1024];
x() { printf("original x address %p\n", this); }
};
__attribute__((noinline)) x make_x() {
return x();
}
} // namespace
int main() {
auto x1 = make_x();
printf("copy of x address %p\n", &x1);
}
由于我对gcc生成的汇编的理解非常有限,我和我的一个同事分析了生成的汇编代码。今天晚些时候,我使用 clang 和 -S -emit-llvm
标志来生成 LLVM assembly我个人认为它比 X86 Assembly/GAS Syntax 更好更易读。 .无论使用哪种编译器,结论都是一样的。
我用C++重写了生成的程序集,如果x
为空,大概是这样的:
#include <cstdio>
using namespace std;
struct x { };
void make_x() {
x tmp;
printf("original x address %p\n", &tmp);
}
int main() {
x x1;
make_x();
printf("copy of x address %p\n", &x1);
}
如果 x
很大(int dummy[1024];
成员未注释):
#include <cstdio>
using namespace std;
struct x { int dummy[1024]; };
void make_x(x* x1) {
printf("original x address %p\n", x1);
}
int main() {
x x1;
make_x(&x1);
printf("copy of x address %p\n", &x1);
}
事实证明,如果对象为空,make_x()
只需打印一些有效的、唯一的地址。如果对象为空,make_x()
可以自由地打印一些指向它自己的堆栈的有效地址。也没有什么可复制的,也没有什么可以从 make_x()
返回。
如果你使对象变大(例如添加 int dummy[1024];
成员),它会在适当的位置构建,因此 RVO 会启动,并且只有对象的地址会传递给make_x()
被打印。没有对象被复制,没有任何东西被移动。
如果对象为空,编译器可以决定不将地址传递给 make_x()
(那会是多么浪费资源?:))但让 make_x()
从它自己的堆栈中组成一个唯一的、有效的地址。这种优化发生的时间有些模糊且难以推理(这就是您在 y
中看到的),但这并不重要。
在重要的情况下,RVO 似乎会持续发生。而且,正如我之前的困惑所表明的那样,甚至整个 make_x()
函数都可以内联,因此首先没有要优化掉的返回值。
关于c++ - RVO 在失败时强制编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19262009/
是否有任何库或框架旨在促进从另一种成熟的编程语言中构建项目? 在 C++、java 等编程语言中指定逻辑、集合和复杂规则非常容易,但在 Makefile 中完成这些事情似乎是一场艰苦的战斗。我还没有深
我有这段代码可以用 clang 编译得很好(即使使用 -Weverything),但是 gcc 会发出错误。 #include #include #include using namespace
我有以下 block 头文件 BKE_mesh.h: /* Connectivity data */ typedef struct IndexNode { struct IndexNode *
我在我的一个项目中遇到了一个奇怪的问题。我的代码库依赖于一个外部库,其中包含一个名为 Dataset 的类. Dataset类私有(private)继承自 std::vector (其中 Sample
当使用 gcc、g++ 或 make 在终端中编译一个小型 C 或 C++ 项目时,我收到以下错误: /tmp/ccG1caGi.o: In function `main': main.c:(.tex
我正在尝试从 CVS 为 Windows 上的 Emacs 23.1.50 编译 CEDET,但在“第 6 步:打开 EDE...”时出现错误:“defvar:作为变量的符号值是无效的:cedet-m
我正在(重新)学习编程,我从 C 开始。我的 IDE(如果我可以这么说)是 Windows7 上的 cygwin(32 位)和 Visual-Studio 2010。我总是编译我用 gcc (cygw
我喜欢在模板类中使用本地类来执行类似“static if”的构造。但是我遇到了 gcc 4.8 不想编译我的代码的问题。但是 4.7 可以。 这个例子: #include #include #in
我有一个项目,必须仅使用 java 1.4 进行编译。但我计划使用mockito 编写一些单元测试。我想要一种在 pom 中指定的方法,以便 src/main/java 使用 jdk 1.4 编译,但
我想了解 PHP 编译过程是如何工作的。 假设我有一个名为funcs.php 的文件并且这个文件有三个函数,如果我include 或require 它,所有的在文件加载期间编译三个函数?或者源代码会被
编译工具链 我们写程序的时候用的都是集成开发环境 (IDE: Integrated Development Environment),集成开发环境可以极大地方便我们程序员编写程序,但是配置起来
当我编写一些 Scala 代码时,在尝试编译代码时收到一条奇怪的错误消息。我将代码分解为一个更简单的代码(从语义的角度来看这完全没有意义,但仍然显示了错误)。 scala> :paste // Ent
我正在编译一个 SCSS 文件,它似乎删除了我的评论。我可以使用什么命令来保留所有评论? >SASS input.scss output.css 我在 SCSS 中看到两种类型的注释。 // Comm
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
当您编译 grails war 时,我知道 .groovy 代码被编译为字节码类文件,但我不明白容器(例如 tomcat)如何在请求 GSP 时知道如何编译它们。容器了解 GSP 吗?安装在服务器上的
我正在努力将多个文件编译成一个通用程序。我收到一个错误: undefined reference to 'pi' 这是我的代码和 Makefile 的框架。我做错了什么?谢谢! 文件:calcPi.c
我尝试使用 LD_PRELOAD 来 Hook sprintf function ,所以我将打印到缓冲区的结果: #define _GNU_SOURCE #include #include int
我正在寻找最简单的方法来自动将 CoffeeScript 重新编译为 JS。 阅读documentation但仍然很难得到我想要的东西。 我需要它来监视文件夹 src/ 中的任何 *.coffee 文
我想使用定制waveformjs 。我发现this on SO但是,我不知道如何编译/安装波形来开始。我从 GitHub 克隆它并进行了更改,但是我不知道如何将其转换为 .js 文件。 最佳答案 为了
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我是一名优秀的程序员,十分优秀!