让按值返回的函数堆分配返回值的最佳方法是什么



假设我有一个简单的函数returnString,它按值返回字符串:

std::string returnString() {
std::string s;
// Use s in such a way to defeat return value mandatory copy-elision
return s;
}

我有另一个函数,它想对这个结果进行堆分配。很简单。

void caller() {
std::string* heap_allocated_string = new std::string(returnString());
}

不过,考虑一个任意类型的T,而不是std::string。我相信,根据语言规则,以下两种说法是正确的。是吗?

  1. 在C++14中,我认为这并不理想,因为对于某些类型,如果move ctor不是自由的或没有定义,与直接在堆上构建相比,我们可能会做不必要的工作
  2. 在C++17中,这会触发强制的副本省略,因此即使类型没有定义移动构造函数,也不会创建额外的副本,也不会调用移动构造函数

一般来说,对于泛型类型,有没有更好的方法可以做到这一点,而不修改被调用的函数?

在C++14中,我认为这并不理想,因为对于某些类型,如果移动ctor不是自由的或没有定义,与直接在堆上构建相比,我们可能会做不必要的工作。

定义"不理想";。

如果对象必须通过一个按值返回的工厂函数来构造,而你想堆分配对象,那么你必须这样做"在不修改被调用函数的情况下;那么这已经是最好的了。

另外,您不必担心C++14中缺少复制/移动。原因是(几乎(不可能在C++14中按值返回不可复制、不可移动的对象。从技术上讲,有一种方法可以做到这一点(通过在return语句中使用列表初始化语法(,但如果函数是按照您所说的那样编写的,那么它返回的任何类型都必须是可复制或可移动的。

此外,你端的new表达式甚至不需要命名的RVO;这部分只是删除了一个临时的,编译器没有理由不能优化这个移动。

因此,基本上,必须有一个复制/移动构造函数来编译函数,并且任何复制/移动都将在您端进行优化,以实现所有实际目的。所以没什么好担心的。

最新更新