2

考虑以下(有点构思)的例子:

// a.cpp
int mystrlen(const char* a) {
   int l = 0;
   while (a[l]) ++l;
   return l;
}

// b.cpp
extern int mystrlen(const char*);
int foo(const char* text) {
   return mystrlen(text) + mystrlen(text);
}

能够告诉编译器mystrlen()没有副作用,因此它可以重用旧结果mystrlen(text)而不是调用它两次,这将是非常好的。

我在文档中没有找到任何关于它的内容,restrict或者它的其中一个差异似乎也不起作用。查看所有优化 (switch /Ox) 的输出代码表明编译器确实生成了两个调用。如果我将这两个功能放在一个模块中,它甚至会这样做。

对此有任何解决方案,或者任何人都可以确认 VC++ 中没有解决方案吗?

4

3 回答 3

1

MSVC 不支持纯/常量属性,也无意支持它们。请参阅https://connect.microsoft.com/VisualStudio/feedback/details/804288/msvc-add-const-and-pure-like-function-attributes。其他编译器,例如 GCC 和 Clang,确实支持这些属性。另请参阅不同编译器中的纯/常量函数属性

于 2015-07-07T14:31:20.673 回答
0

你正在寻找的东西对你没有帮助。

一般来说,编译器不能省略调用,即使认为该函数没有副作用。你从哪里得到那个指针?信号处理程序是否可以访问相同的指针?也许另一个线程?编译器如何知道指针指向的内存不会从它下面改变?

编译器确实经常消除函数体中的冗余获取,即使是通过指针获取的东西。但是他们可以甚至应该做多少是有限度的。

在这里,您要求编译器相信您拥有的指向谁知道在哪里的裸指针将在两个函数调用之间保持一致的内容。这是很多假设。当然你还没有声明你的指针是易变的,但仍然有很多假设。

现在,如果您在堆栈上有一个缓冲区并且连续两次将其传递给该函数,编译器可以非常安全地假设如果您没有将指针传递到其他地方,那么该缓冲区的内容不会去在某个意想不到的时间被程序中一些随机的其他东西改变。

例如:

// b.cpp
extern int mystrlen(const char*);
int foo(int bar) {
   char number[20];
   snsprintf(number, 20, "%d", bar);
   return mystrlen(number) + mystrlen(number);
}

假设编译器可以假设snprintfnumber是一个库函数,那么它可以省略第二次调用,mystrlen如果有一种方法可以声明mystrlen没有副作用。

于 2017-03-19T00:05:53.333 回答
-1

因为 C++ 是一种命令式语言而不是函数式语言,所以您想要实现的目标是不可能的。

看起来您在这里期望的行为是引用透明性,在 C++ 中没有办法告诉编译器(但在像 Haskell 这样的纯函数式编程语言中是隐式的)。

希望未来的 C++ 标准将引入一个关键字,允许我们将函数标记为“纯”或“无副作用”。

于 2013-11-04T09:22:43.477 回答