When是复制的向量,When是传递的引用
When is a vector copied, when is a reference passed?
我正在使用一个大量使用std::vector
的程序。还有很多分配/释放正在发生,数十亿,我试图避免尽可能多的。由于我对c++比较陌生,所以在使用vector(例如向其添加元素)时,我有一些关于分配的问题。我在Win7 64位的机器上,程序是32位的,我使用的是当前版本的mingw编译器。
我想知道,在以下情况下会发生什么,即如果向量被复制,作为引用传递,…
1。
std::vector<T> fillVector() {
std::vector<T> returnVector;
...
return returnVector;
}
std::vector<T> myVector = fillVector();
2。
std::vector<T>& fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return (*returnVector);
}
std::vector<T> myVector = fillVector();
3。
std::vector<T>* fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return returnVector;
}
std::vector<T>* myVector = fillVector();
和以下不同的操作:
4。
std::vector<T> myVector1;
... (myVector1 being filled)
std::vector<T> myVector = myVector1;
5 .
std::vector<T>* myVector1 = new std::vector<T>;
... (myVector1 being filled)
std::vector<T> myVector = (*myVector1);
假设我不想更改myFunction
中的参数/将myFunction
中的参数更改为myVector
不会影响程序的其余部分:
6。
void myFunction(std::vector<T> myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
7。
void myFunction(std::vector<T>& myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
如果我的理解是正确的,最快的选项(意思是传递引用而不是创建副本并传递它们)将是2/3,5和7。如果我说错了,请纠正我!
1.
std::vector<T> fillVector() {
std::vector<T> returnVector;
...
return returnVector;
}
std::vector<T> myVector = fillVector();
这很好。vector
通过值返回,但是大多数编译器(至少在打开优化时)在(命名的)返回值优化下省略了对复制构造函数的调用。
此外,在c++ 11中,move语义确保调用move构造函数而不是复制构造函数,后者只会窃取返回向量的核心,而不会生成代价高昂的副本。
2。
std::vector<T>& fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return (*returnVector);
}
std::vector<T> myVector = fillVector();
不要这样做。动态分配的不必要开销,加上必须记住必须释放返回对象的负担。避免手动内存管理,首选1.
3。
std::vector<T>* fillVector() {
std::vector<T>* returnVector = new std::vector<T>;
...
return returnVector;
}
std::vector<T>* myVector = fillVector();
同上。避免手动内存管理。
4。
std::vector<T> myVector1;
... (myVector1 being filled)
std::vector<T> myVector = myVector1;
这是一个概念上不同的操作。这里你想要创建一个副本,看起来你做得对。在c++ 11中,如果你只需要传输 myVector1
的内容,而不是复制它,你可能想使用std::vector<T> myVector = std::move(myVector1)
。
5 .
std::vector<T>* myVector1 = new std::vector<T>;
... (myVector1 being filled)
std::vector<T> myVector = (*myVector1);
和上面一样,你想要创建一个拷贝,但是你没有必要动态地分配vector。这将再次迫使您手动处理它的生命周期,这很糟糕,而且容易出错。不要这样做。
6。
void myFunction(std::vector<T> myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
在这里你通过值传递myVector
。这是否可以优化取决于myFunction
应该如何处理它的参数:它应该改变它吗?如果是这样,您希望从函数返回后这些更改是可见的吗?如果是,按值传递是正确的,并且没有办法优化它,除非您想要获得myVector
对象:在这种情况下,在c++ 11中,您可以在将传递给函数时移动。这将避免昂贵的、不必要的复制。
7。
void myFunction(std::vector<T>& myParam) {
...
}
std::vector<T> myVector;
... (myVector being filled)
myFunction(myVector);
这将通过引用传递,只要在从函数返回后可以看到myFunction
对myVector
的副作用就可以。一般来说,不能告诉它是否正确,这取决于应用程序的特定逻辑。
最快且最惯用的是选项1。两个副本(从returnVector
到返回值和从返回值到myVector
)几乎肯定会被编译器省略。拷贝省略是编译器可能进行的一种优化,涉及删除任何不必要的拷贝。在这里,两个副本都是不必要的,std::vector
将直接构造代替myVector
。
实际上,即使在编译器中禁用了复制省略优化,在c++ 11中,两个副本实际上都是移动的。移动std::vector
需要几个任务,并且非常快。第一个被特殊规则认为是移动,第二个是移动,因为表达式fillVector()
是一个右值表达式。
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 编译C++时未定义的引用
- Ctypes wstring通过引用传递
- c++r值引用应用于函数指针
- 理解c++中的引用
- C++取消引用指针.为什么会发生变化
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 强制转换为引用类型
- 引用一个已擦除类型(void*)的指针
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 具有默认值的引用获取函数
- 如何使用基类指针引用派生类成员
- 在c++ 11中,When是比按值传递更好的const引用
- When是复制的向量,When是传递的引用