通过函数传递引用是安全的吗?

18

下面的函数在C++03或C++11中是否安全,还是会出现未定义行为?

string const &min(string const &a, string const &b) {
    return a < b ? a : b;
}

int main() {
    cout << min("A", "B");
}
  • 将对象通过引用传递给函数后,返回该对象的引用是否可行?

  • 临时 string 对象是否保证不会过早销毁?

  • 如果在给定的上下文中没有 UB,那么给定的函数 min 是否可能出现 UB?

  • 是否有可能创建一个等效但安全的函数,同时避免复制或移动操作?


你需要使用std字符串吗?如果您绝对想避免临时变量,可以使用std::strcmp() - bluescarni
@bluescarni:无论是string还是其他临时对象类型都没有关系。问题的意思是通用的。 - Juraj Blaho
5个回答

29

将通过引用传递给函数的对象返回引用,是否可行?

只要在通过引用访问该对象之前它没有被销毁,那么是可以的。

临时 string 对象是否保证不会过早销毁?

在这种情况下,是的。临时对象会持续到创建它的完整表达式结束,在被流输出到 cout 之后才被销毁。

如果给定上下文中未出现问题,min 函数是否有可能出现 UB(未定义行为)?

是的,以下是一个例子:

auto const & r = min("A", "B"); // r is a reference to one of the temporaries
cout << r;                      // Whoops! Both temporaries have been destroyed

是否可能制作一个等效但安全的函数而仍然避免复制或移动?

我认为不可能,但只要您不保留对其结果的引用,此函数就是安全的。


1
我确定这是不可能的,因为那需要一个完整的 GC。你需要追踪临时对象是否还有引用。 - MSalters
1
该函数本身并没有真正执行任何未定义的操作(只要参数有效,返回的引用将保持有效)... 在我看来,是使用方式导致了问题。 - nishantjr
编译器在这种情况下可以防止复制,如果可行的话。然而,这取决于您的编译器和优化级别。例如,GCC将使用“-O2”或更高级别来防止复制临时返回值。 - Symaxion

4

你的临时对象将一直保持“活着”的状态,直到在主函数中从cout;结束,所以这种使用方式是安全的。


2

是的,很安全。字符串 "A" 和 "B" 的 temps 将在“序列点”(即分号)结束之前一直存在。


1

临时字符串对象是否保证不会过早销毁?

对于您的特定情况是,但对于以下代码不是。

int main() {
    const string &tempString(min("A", "B"));
    cout << tempString;
}

除此之外,我同意“Mike Seymour”所说的话。

1
如果有一个const关键字用于临时引用,那就好了。 - miguel.martin
谢谢,现在正在编译并显示问题所在的情况。 - Roee Gavirel

0

通过函数传递引用是安全的,因为在传递值时总是对参数进行更改。在上面的代码中,字符串temps对于A和B都将存活到“序列点”即分号结束之前,但是在传递引用的情况下,更改是在该参数的副本而不是原始副本中进行的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接