我正在使用一个充分利用它的程序std::vector.还有很多分配/解除分配,数十亿分配,我试图避免尽可能多的分配/解除分配.由于我对C++比较陌生,所以我在使用向量时会有一些关于分配的问题(例如,在向其添加元素时).我在Win7 64位机器上,程序是32位,我正在使用当前版本的MinGW编译器.
我想知道,在下列情况下会发生什么,即如果复制了矢量,作为参考传递,...
1.
std::vector<T> fillVector() {
std::vector<T> returnVector;
...
return returnVector;
}
std::vector<T> myVector = fillVector();
Run Code Online (Sandbox Code Playgroud)
2.
std::vector<T>& fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return (*returnVector);
}
std::vector<T> myVector = fillVector();
Run Code Online (Sandbox Code Playgroud)
3.
std::vector<T>* fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return returnVector;
}
std::vector<T>* myVector = fillVector();
Run Code Online (Sandbox Code Playgroud)
以下是不同的操作:
4.
std::vector<T> myVector1;
... (myVector1 being filled)
std::vector<T> myVector = myVector1;
Run Code Online (Sandbox Code Playgroud)
5.
std::vector<T>* myVector1 = new std::vector<T>;
... (myVector1 being filled)
std::vector<T> myVector = (*myVector1);
Run Code Online (Sandbox Code Playgroud)
假设我不想改变myFunction/中的参数改为myVectorin myFunction会不会伤害程序的其余部分:
6.
void myFunction(std::vector<T> myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
Run Code Online (Sandbox Code Playgroud)
7.
void myFunction(std::vector<T>& myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
Run Code Online (Sandbox Code Playgroud)
如果我的理解是正确的,最快的选择(意味着传递参考而不是创建副本并传递它们)将是2/3,5和7.如果我错了,请纠正我!
1.
std::vector<T> fillVector() {
std::vector<T> returnVector;
...
return returnVector;
}
std::vector<T> myVector = fillVector();
Run Code Online (Sandbox Code Playgroud)
这可以.它vector是按值返回的,但大多数编译器(在命名的)返回值优化下都会忽略对复制构造函数的调用(至少在启用优化时).
此外,使用C++ 11,移动语义确保调用移动构造函数而不是复制构造函数,这将简单地窃取返回向量的内容,而不会生成昂贵的副本.
2.
std::vector<T>& fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return (*returnVector);
}
std::vector<T> myVector = fillVector();
Run Code Online (Sandbox Code Playgroud)
不要这样做.动态分配的不必要的开销,加上必须记住您必须释放返回的对象的负担.避免手动内存管理,更喜欢1.
3.
std::vector<T>* fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return returnVector;
}
std::vector<T>* myVector = fillVector();
Run Code Online (Sandbox Code Playgroud)
与上述相同.避免手动内存管理.
4.
std::vector<T> myVector1;
... (myVector1 being filled)
std::vector<T> myVector = myVector1;
Run Code Online (Sandbox Code Playgroud)
这是一个概念上不同的操作.在这里你要创建一个副本,看起来你做得对.在C++ 11中,std::vector<T> myVector = std::move(myVector1)如果您只需要传输内容myVector1而不是复制内容,则可能需要使用它.
5.
std::vector<T>* myVector1 = new std::vector<T>;
... (myVector1 being filled)
std::vector<T> myVector = (*myVector1);
Run Code Online (Sandbox Code Playgroud)
与上面相同,您想要创建一个副本,但是您不必要地动态分配向量.这将再次迫使您手动处理它的生命周期,这很糟糕且容易出错.不要这样做.
6.
void myFunction(std::vector<T> myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
Run Code Online (Sandbox Code Playgroud)
在这里,你正在经历myVector价值.这是否可以优化取决于myFunction它的论点是什么:它会改变它吗?如果是这样,您是否希望在从函数返回后可以看到这些更改?如果是,则按值传递是正确的,除非您想要获取myVector对象,否则无法对其进行优化:在这种情况下,在C++ 11中,您可以在将其传递给函数时将其移动.这将避免昂贵的,不必要的副本.
7.
void myFunction(std::vector<T>& myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
Run Code Online (Sandbox Code Playgroud)
这将通过引用传递,只要在从函数返回后看到myFunctionon 的副作用就myVector可以了.一般不能告诉它是否正确,这取决于您的应用程序的特定逻辑.
最快且最惯用的是选项 1。两个副本(从returnVector到 返回值 和从 返回值 到myVector)几乎肯定会被编译器删除。复制省略是编译器可能进行的一种优化,涉及删除任何不必要的副本。在这里,两个副本都是不必要的,std::vector将直接构建来代替myVector。
事实上,即使您使用编译器禁用复制省略优化,在 C++11 中,两个副本实际上都会移动。移动 astd::vector需要一些任务,而且速度非常快。第一个被特殊规则视为移动,第二个被视为移动,因为该表达式fillVector()是右值表达式。
| 归档时间: |
|
| 查看次数: |
3322 次 |
| 最近记录: |