C++ 可以在堆上分配右值向量吗?

C++ 可以在堆上分配右值向量吗?,c++,C++,我不确定我在这里使用的术语是否正确,但假设我有一个返回向量的函数: std::vector<int> func() { std::vector<int> vec(100,1); return vec; } std::vector func() { std::vec(100,1); 返回向量; } 当我调用这个函数时,我想在堆上分配向量。我能做这个吗 我的想法大致如下: std::shared_ptr<std::vector<int>&

我不确定我在这里使用的术语是否正确,但假设我有一个返回向量的函数:

std::vector<int> func()
{
    std::vector<int> vec(100,1);
    return vec;
}
std::vector func()
{
std::vec(100,1);
返回向量;
}
当我调用这个函数时,我想在堆上分配向量。我能做这个吗

我的想法大致如下:

std::shared_ptr<std::vector<int>> vec(new std::vector<int>);
vec->swap(func());
std::shared_ptr vec(新std::vector);
向量->交换(func());

有没有一种方法可以在不更改
func()
的情况下减少复杂度?

我能想到的唯一更好的方法是不使用
std::move
,因为编译器会自动执行RVO

第二个表达式可以稍微缩短:

std::vector<int>* vec2 = new std::vector<int>( f() );
std::vector*vec2=新的std::vector(f());

就像其他人所说的,在堆上分配向量并不是真正必要的

只要试着删除
std::move
,这是一个特定的编译器异常,以避免您放置
std::move
,让编译器来完成其余的工作

std::vector<int> func()
{
    std::vector<int> vec(100,1);
    return vec; // NOT: return std::move(vec);
}
std::vector func()
{
std::vec(100,1);
return-vec;//NOT:return-std::move(vec);
}
为什么?

因为,自动对象
vec
将在执行
return
后销毁,在这种情况下,它的行为与右值相同。然后编译器将移动它。放置
std::move
会使编译器对NRVO感到恼火


返回向量的简单方法是优化的,不必担心性能。

我不知道您在做什么,如果您希望系统内存中有更多的片段,您可以从堆栈中优化多少而不进行任何权衡,或者从堆中优化多少?如果您有数百万条记录需要在“您的堆”上分配,我想到的第一件事是,您的代码中可能存在的操作会损坏它。第二,堆大小是有限的,那么您需要重新实现分配器来处理“如何处理要存储的小内存和大数据”。 如果您坚持优化策略而不是堆管理,那么返回指向向量的指针似乎是有希望的

std::vector<int*>* yourfunc()
{
    // do something
    return pVec;
}
std::vector*yourfunc()
{
//做点什么
返回pVec;
}

然后应用了
new
方法,但仍然需要在末尾删除对象。

不确定要执行的操作。一个
vector
的内容(它包含的
T
的实际数组)无论如何都会分配到堆上,除非您通过提供一个特殊的分配器(
std::vector
)来另外指定。不要在这里使用
std::move
,它会阻止优化。也许您只是想要
std::vector*func(){返回新的std::vector(100, 1); }
?但是使用标准容器的原始指针几乎总是一个坏主意——你最终想要实现什么?你可能会想使用
std::unique\u ptr
而不是
shared\u ptr
,因为你不需要
shared\u ptr
@j\u random\u hacker的引用计数,我想保留一个共享指针在函数退出后,它保持向量存活,但我不想返回函数中的指针…显然对于向量和它的元素都不知道。后面的代码是什么?@阿曼施瓦茨:那么,在C++ 11中,只需简单地返回代码<代码>返回VEC;< /C> >,即使在以前的C++版本中,也有RVO避免了那些ReDU。大量的动作。@MM。我就是这么做的。哦,你的意思是因为
std::move
?我明白为什么错了,我现在把它删除了。但这并不是问题的关键。“当你说它错了,那么它就错了。”–这不是我通常想要鼓励的观点。:/p不幸的是,我现在不想费心在标准中寻找证据;然而,这里有一个例子证明了这至少在某些情况下是正确的:@KonradRudolph:使用
-fno elide构造函数编译代码来禁用elide,我认为它显示了
f()
编译器试图移动,不是吗?然后,我们可以得出结论,编译器在返回时移动了对象。这只是我的猜测,可能我的结论是错误的。啊,我现在明白你的意思了。是的,如果它不能删除副本,构造函数将在返回时尝试移动。不幸的是,我的初始注释被删除了(?!–不是我写的!)所以我不能再检查我到底写了什么。