C++ 按值将向量返回到引用中
我有以下代码:C++ 按值将向量返回到引用中,c++,C++,我有以下代码: std::vector<Info*> filter(int direction) { std::vector<Info*> new_buffer; for(std::vector<Info*>::iterator it=m_Buffer.begin();it<m_Buffer.end();it++) { if(((*it)->direction == direction) {
std::vector<Info*> filter(int direction)
{
std::vector<Info*> new_buffer;
for(std::vector<Info*>::iterator it=m_Buffer.begin();it<m_Buffer.end();it++)
{
if(((*it)->direction == direction)
{
new_buffer.push_back(*it);
}
}
return new_buffer;
}
std::vector<Info*> &filteredInfo= filter(m_Direction);
std::向量过滤器(int方向)
{
std::向量新_缓冲区;
对于(std::vector::iterator it=m_Buffer.begin();itdirection==direction)
{
新建缓冲区。将缓冲区向后推(*it);
}
}
返回新的缓冲区;
}
std::vector&filteredInfo=过滤器(m_方向);
有人能解释一下这里发生了什么吗?filter方法是否会按值返回创建一个临时值,而filteredInfo不会因为是引用而被销毁
不知道我是否理解正确。在这种情况下,filteredInfo作为引用和不作为引用之间有什么区别?编译器应该抱怨这段代码 本声明:
std::vector<Info*> &filteredInfo= filter(m_Direction);
您正在尝试创建对临时对象的引用。即使你的编译器成功了,它也是非法的
你应使用:
std::vector<Info*> filteredInfo= filter(m_Direction);
std::vector filteredInfo=过滤器(m_方向);
它的效率是你想要的。一个move
操作(C++11)将在那里发生,或者将启动。对于过滤器的实现
,它应该是基于优化构建的RVO(但这取决于编译器的质量)
但是,您应该注意,您正在将原始指针复制到向量中,我希望您有一个正确的所有权模型?如果没有,我建议您使用智能指针。以下是发生的情况:
std::vector新建\u缓冲区代码>在本地创建对象
返回新的\u缓冲区调用filter(m\u方向)
时,code>将new\u buffer
移动到临时对象
std::vector filteredInfo=filter(m_方向)
临时对象将被移动到filteredInfo
,因此没有不必要的副本,这是最有效的方法std::vector&filteredInfo=filter(m_方向)
然后将filteredInfo
绑定到一个临时对象,这是一个糟糕的想法,大多数编译器都会对此抱怨在这里,你正确地感到困惑,因为有两个独立的奇怪事实混合在一起:
- 编译器允许将非常量引用绑定到临时引用。从历史上看,这在Microsoft编译器中是一个错误,标准不允许这样做。该代码不应编译
- 然而,奇怪的是,该标准实际上允许绑定
对临时对象的引用,并为此制定了一条特殊规则:临时对象不会立即被销毁(就像通常发生的那样),但其寿命将延长到引用的寿命const
std::vector<int> foo() {
std::vector<int> x{1,2,3};
return x;
}
int main() {
const std::vector<int>& x = foo(); // legal
for (auto& item : x) {
std::cout << x << std::endl;
}
}
不能打电话给我
foo("Hey, you");
没有特殊规则,因为常量char*
(literal)被隐式转换为临时std::string
,并作为绑定到常量引用的参数传递
(1) 从哲学的角度来看,这种模式确实很糟糕,因为一个值就是一个值,一个引用就是一个引用:这两个概念在逻辑上是不同的。然而,C++是性能困扰,尤其是在移动语义之前,传递const引用被认为是传递值的“智能”方式,尽管是一个问题,因为生命周期和混淆问题,并且使优化器变得更困难。在现代编译器中,传递引用应该只用于“大”对象,特别是那些不是要传递的动态构造的对象,或者当您真正感兴趣的是对象标识而不仅仅是对象值时。这个编译吗?如果有,您使用的是MSV吗?是的,它的Visual Studio 2005还可以。请注意,这是非标准代码。MSVS允许这样做,但这在大多数其他编译器上不起作用。请提供一个。这会导致内存泄漏吗?当使用对临时?Kobe的引用时,这不是内存泄漏,但如果使用该引用,则肯定是UB。MSVC(Visual Studio)在这里做了一些很好的定义,但它确实依赖于编译器,而不是标准Com共振
void foo(const std::string& x) { ... }
foo("Hey, you");