【问题标题】:How many temporary objects are created when I return a string from an inline function?当我从内联函数返回一个字符串时,会创建多少个临时对象?
【发布时间】:2013-12-03 20:10:52
【问题描述】:

考虑以下代码:

QSqlQuery *queryQt; // represents a row in a database table

inline std::string getCString(size_t col) {
     return queryQt->value(col).toString().toStdString();
}

其中queryQt->value(col).toString()表示数据库中行的特定列的字符串值。

让我们假设编译器已开启所有优化。

问题:是下面的代码:

std::string a = T.getCString(0);

相当于

std::string a = queryQt->value(col).toString().toStdString();

或到

std::string temp = queryQt->value(col).toString().toStdString();
std::string a = temp;

?

问题更新:

如果我在返回类型中添加 const 会有什么不同吗?

【问题讨论】:

  • 你看过程序集吗?
  • @constantin 不是真的。这是代码的简化版本,我在其中返回 const 数据等。但是感谢您的提示..
  • 由于允许复制省略,这可能会有所不同。但是你总是可以通过让你的ctors(和dtors)冗长来在你的编译器(和标志)中尝试它。

标签: c++ string inline-code


【解决方案1】:

因为下面的代码是初始化a而不是分配给它

std::string a = T.getCString(0);

等价于

std::string a(T.getCString(0)); // Construct "a" with return value of function.

std::string a(std::string(queryQt->value(0).toString().toStdString()));

这意味着当从函数返回时会有一个std::string 的复制构造,而当从返回值构造a 时会有另一个复制构造。所以 2 份。

但是在 C++11 编译器上,move 构造 将在构造返回值和 a 时被使用,因为 std::string 构造的对象都是临时对象。这意味着将只有 2 个移动而不是 2 个副本。

最后因为copy elision optimizations,编译器很可能会一起忽略所有副本,并直接在a 中构造std::string,导致根本没有副本。

内联函数与复制的数量无关。将返回类型更改为 const 将阻止移动构造,因为您无法从 const 对象移动。

Look at this live example using my noisy class

【讨论】:

  • 将返回类型更改为 const 意味着在 C++11 中它是从复制而来,而不是从移动而来(你不能从 const 对象移动,即使是临时对象)。所以原则上它可能会影响副本的数量,但如果复制/移动被省略,它不会影响数量。
  • @Snps 哇。有一个 const 是多么令人惊讶的效果!非常漂亮和直观的解释
【解决方案2】:

相当于

std::string temp = queryQt->value(col).toString().toStdString();
std::string a = temp;

至少在理论上。根据您的实际编译器及其设置,该函数可能不会被内联,即使使用 inline 关键字也是如此。大多数现代编译器(在发布设置上)也会将代码优化为

std::string a = queryQt->value(col).toString().toStdString();

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 2019-12-29
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2012-02-26
    • 1970-01-01
    相关资源
    最近更新 更多