当必须转换类型时,通过 const 引用传递是否真的节省了内存成本?
Does passing by const reference really save the memory cost when it has to convert the type?
关于const
引用(对const的引用)存在很多问题。但是当有隐式转换时,const
引用也会产生一个新的地址。我在下面写了这个例子:
int i = 42;
double d = 4.2;
const int& ri1 = i;
const int& ri2 = d;
&ri1
和 &i
会打印相同的地址,但是 &ri2
和 &d
是不同的。 ri2
真正服务的对象是什么?正如 “C++ Primer” 所说,它会生成一个临时对象。但是如果转换后的 const 引用使用了差异地址,那意味着这个地址仍然有一个有效的对象。
假设我有一个很大的长 string
或 const char*
作为“长示例文本”并将其传递给某个接受 const string&
的函数,会有类似的转换。
确实有一个未命名的 int
对象,值为 4。这需要一点内存。
对于 std::string
示例,const string&
可以绑定到 string
参数而不会导致复制。但是 const char*
参数会导致复制。你可以考虑 std::string_view
.
这样想很有帮助:
我们不希望将 (plain) &
引用绑定到一个对象,如果此绑定会导致此对象更改。例如。从 3.1415 到 3,如下所示:
double pi = 3.1415;
int& r = pi; // Imagine, now both r and pi are 3...
我们不能将 r
的类型更改为 double
(否则,这对于该语言来说将是一种逻辑!)。
而且我敢肯定大多数 C++ 用户不希望将 pi
的值更改为 3(因为 r
是 int
)作为引用绑定的结果。
我们需要通过将 pi
转换为 r
的类型来创建一个新对象。当我们发生转换时,引用将绑定到作为此转换结果创建的临时对象。
没有理由对这个我们没有其他(除了引用“handle”)的未命名对象进行非const
引用使用权。如果我们出于某种原因想要更改它,我们可以将 pi
复制到 int i
并将 i
更改为我们想要的任何内容。
回答你问题的要点:
是的,会造成额外的负担,万一从const char*
到 const string&
,但这可能 不是 const string&
.
的预期用途
为什么?因为如果您确定地知道,比方说,您的函数将被传递一个 const char*
(而且只有它),并且您负担不起任何开销,那么您为什么要声明一个像 const string&
这样的参数。 好吧,可能有几个正当的理由,所有这些理由都值得开销。
在其他情况下,当传递 string
时,您将避免复制。双赢的局面,不是吗?
关于const
引用(对const的引用)存在很多问题。但是当有隐式转换时,const
引用也会产生一个新的地址。我在下面写了这个例子:
int i = 42;
double d = 4.2;
const int& ri1 = i;
const int& ri2 = d;
&ri1
和 &i
会打印相同的地址,但是 &ri2
和 &d
是不同的。 ri2
真正服务的对象是什么?正如 “C++ Primer” 所说,它会生成一个临时对象。但是如果转换后的 const 引用使用了差异地址,那意味着这个地址仍然有一个有效的对象。
假设我有一个很大的长 string
或 const char*
作为“长示例文本”并将其传递给某个接受 const string&
的函数,会有类似的转换。
确实有一个未命名的 int
对象,值为 4。这需要一点内存。
对于 std::string
示例,const string&
可以绑定到 string
参数而不会导致复制。但是 const char*
参数会导致复制。你可以考虑 std::string_view
.
这样想很有帮助:
我们不希望将 (plain) &
引用绑定到一个对象,如果此绑定会导致此对象更改。例如。从 3.1415 到 3,如下所示:
double pi = 3.1415;
int& r = pi; // Imagine, now both r and pi are 3...
我们不能将 r
的类型更改为 double
(否则,这对于该语言来说将是一种逻辑!)。
而且我敢肯定大多数 C++ 用户不希望将 pi
的值更改为 3(因为 r
是 int
)作为引用绑定的结果。
我们需要通过将 pi
转换为 r
的类型来创建一个新对象。当我们发生转换时,引用将绑定到作为此转换结果创建的临时对象。
没有理由对这个我们没有其他(除了引用“handle”)的未命名对象进行非const
引用使用权。如果我们出于某种原因想要更改它,我们可以将 pi
复制到 int i
并将 i
更改为我们想要的任何内容。
回答你问题的要点:
是的,会造成额外的负担,万一从const char*
到 const string&
,但这可能 不是 const string&
.
为什么?因为如果您确定地知道,比方说,您的函数将被传递一个 const char*
(而且只有它),并且您负担不起任何开销,那么您为什么要声明一个像 const string&
这样的参数。 好吧,可能有几个正当的理由,所有这些理由都值得开销。
在其他情况下,当传递 string
时,您将避免复制。双赢的局面,不是吗?