在传统的C++中,将值传递给函数和方法对于大型对象来说是很慢的,并且通常不赞成.相反,C++程序员倾向于传递引用,这更快,但它引入了围绕所有权的各种复杂问题,特别是围绕内存管理(如果对象是堆分配的)
现在,在C++ 11中,我们有Rvalue引用和移动构造函数,这意味着可以实现一个大的对象(比如一个std::vector),它可以通过值传入和传出函数.
那么,这是否意味着默认值应该是传递类型实例的值,例如std::vector和std::string?自定义对象怎么样?什么是新的最佳做法?
我是C++初学者,但不是编程初学者.我正在努力学习C++(c ++ 11),对我来说,最重要的是有点不清楚:传递参数.
我考虑过这些简单的例子:
一个包含其所有成员基本类型的类:
CreditCard(std::string number, int expMonth, int expYear,int pin):number(number), expMonth(expMonth), expYear(expYear), pin(pin)
具有成员基本类型+ 1复杂类型的类:
Account(std::string number, float amount, CreditCard creditCard) : number(number), amount(amount), creditCard(creditCard)
具有成员基本类型的类+具有某种复杂类型的1个集合:
Client(std::string firstName, std::string lastName, std::vector<Account> accounts):firstName(firstName), lastName(lastName), accounts(accounts)
当我创建一个帐户时,我这样做:
CreditCard cc("12345",2,2015,1001);
Account acc("asdasd",345, cc);
Run Code Online (Sandbox Code Playgroud)
显然,在这种情况下,信用卡将被复制两次.如果我重写该构造函数为
Account(std::string number, float amount, CreditCard& creditCard)
: number(number)
, amount(amount)
, creditCard(creditCard)
Run Code Online (Sandbox Code Playgroud)
会有一份副本.如果我把它重写为
Account(std::string number, float amount, CreditCard&& creditCard)
: number(number)
, amount(amount)
, creditCard(std::forward<CreditCard>(creditCard))
Run Code Online (Sandbox Code Playgroud)
将有2个动作,没有副本.
我想有时您可能想要复制一些参数,有时您不希望在创建该对象时进行复制.
我来自C#,用于引用,对我来说有点奇怪,我认为每个参数应该有2个重载,但我知道我错了.
有没有关于如何在C++中发送参数的最佳实践,因为我真的发现它,比方说,并非琐碎.你会如何处理我上面提到的例子?
以下哪个示例是声明以下功能的更好方法?为什么?
void myFunction (const int &myArgument);
Run Code Online (Sandbox Code Playgroud)
要么
void myFunction (int myArgument);
Run Code Online (Sandbox Code Playgroud) 在阅读了@Mehrdad 最近的问题之后,哪些类应该是不可移动的,因此是不可复制的,我开始想知道是否存在可以复制但不能移动的类的用例.从技术上讲,这是可能的:
struct S
{
S() { }
S(S const& s) { }
S(S&&) = delete;
};
S foo()
{
S s1;
S s2(s1); // OK (copyable)
return s1; // ERROR! (non-movable)
}
Run Code Online (Sandbox Code Playgroud)
虽然S有一个复制构造函数,但它显然不会对CopyConstructible概念进行建模,因为这反过来又是MoveConstructible概念的改进,需要存在(未删除的)移动构造函数(参见§17.6.3.1/2,表21) .
是否有类似S上述类型的用例,可复制但不可 CopyConstructible 移动?如果没有,为什么不禁止在同一个类中声明复制构造函数和已删除的移动构造函数?
我为什么要或不应该创建我的所有函数和成员函数来取一个带有a的rvalue版本lvalue?你总是可以转发lvalue到右转,对吧?我甚至可以拥有const rvalue,为什么这是一个坏主意或好主意呢?
我在代码中的意思如下.该"&&" rvalue引用允许用户使用临时对象,并且仍然可以lvalue通过简单的转发使用.所以考虑到这一点,我为什么要提供print_string(string& str)(lvalue参考)c ++ 11中的任何函数(除了const参考,因为rvalue有好的)?
#include <iostream>
#include <string>
#include <utility>
using namespace std;
void print_string(string&& str)
{
str += "!!!";
cout << str << endl;
}
void print_string2(string& str)
{
str += "???";
cout << str << endl;
}
int main(int argc, char* argv[])
{
print_string("hi there"); // works
print_string(string("hi again")); // works
string lvalue("lvalue");
print_string(forward<string>(lvalue)); // …Run Code Online (Sandbox Code Playgroud) 所以我昨天在youtube上观看了c ++视频,遇到了一个关于C++ - 11 rvalue引用和移动语义的视频.我认为我从广义上理解这个概念,但是今天当我通过TA进行我的代码时,他问我为什么std::pair<HostName, IPAddress>& p在下面的代码中没有引用(如).在这种情况下,我根本没有考虑过这个问题,但当他问我记得有关"在C++ - 11中你通常应该使用传值的视频"时.
因此我的问题是:在下面的代码中,是否std::pair<HostName, IPAddress> p会更好std::pair<HostName, IPAddress>& p?是否会使用移动语义,它会有所作为吗?
IPAddress NameServer::lookup( const HostName& host ) const {
auto it = std::find_if( vec.begin(), vec.end(),
[host] ( std::pair<HostName, IPAddress> p ) {
return p.first == host;
} );
...
}
Run Code Online (Sandbox Code Playgroud)