如何正确传递参数? 我是C++初学者,不是编程初学者。 我正在尝试学习C++(C++11),但对我来说,最重要的事情是:传递参数,这有点不清楚 CreditCard cc("12345",2,2015,1001); Account acc("asdasd",345, cc);

如何正确传递参数? 我是C++初学者,不是编程初学者。 我正在尝试学习C++(C++11),但对我来说,最重要的事情是:传递参数,这有点不清楚 CreditCard cc("12345",2,2015,1001); Account acc("asdasd",345, cc);,c++,c++11,C++,C++11,我考虑了这些简单的例子: CreditCard cc("12345",2,2015,1001); Account acc("asdasd",345, cc); 具有其所有成员的类基本类型: CreditCard(std::string number,int-expMonth,int-expYear,int-pin):number(number),expMonth(expMonth),expYear(expYear),pin(pin) CreditCard cc("12

我考虑了这些简单的例子:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
  • 具有其所有成员的类基本类型:
    CreditCard(std::string number,int-expMonth,int-expYear,int-pin):number(number),expMonth(expMonth),expYear(expYear),pin(pin)

  •     CreditCard cc("12345",2,2015,1001);
        Account acc("asdasd",345, cc);
    
  • 成员为基元类型+1复杂类型的类:
    账户(std::字符串编号、浮动金额、信用卡信用卡):编号(编号)、金额(金额)、信用卡(信用卡)

  •     CreditCard cc("12345",2,2015,1001);
        Account acc("asdasd",345, cc);
    
  • 一个类,其成员为基元类型+1个复杂类型的集合:
    客户端(std::string firstName、std::string lastName、std::vector accounts):firstName(firstName)、lastName(lastName)、accounts(accounts)

  •     CreditCard cc("12345",2,2015,1001);
        Account acc("asdasd",345, cc);
    
创建帐户时,我会执行以下操作:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
显然,在这种情况下,信用卡将被复制两次。 如果我将构造函数重写为

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
Account(std::string number, float amount, CreditCard& creditCard) 
    : number(number)
    , amount(amount)
    , creditCard(creditCard)
会有一份。 如果我把它改写成

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
Account(std::string number, float amount, CreditCard&& creditCard) 
    : number(number)
    , amount(amount)
    , creditCard(std::forward<CreditCard>(creditCard))
账户(标准::字符串编号、浮动金额、信用卡和信用卡)
:号码
,金额
,信用卡(标准::远期(信用卡))
将有2个移动,没有复制

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
我认为有时您可能需要复制某些参数,有时您不希望在创建该对象时进行复制。
我来自C#,习惯于引用,这对我来说有点奇怪,我认为每个参数应该有2个重载,但我知道我错了。

是否有任何最佳的实践如何在C++中发送参数,因为我真的发现,这不是微不足道的。您将如何处理我上面介绍的示例?

首先,
std::string
是一个相当庞大的类类型,就像
std::vector
一样。这当然不是原始的

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
如果您要按值将任何大型可移动类型放入构造函数中,我将
std::move
它们放入成员中:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
CreditCard(std::string number, float amount, CreditCard creditCard)
  : number(std::move(number)), amount(amount), creditCard(std::move(creditCard))
{ }
这正是我建议实现构造函数的方式。它使成员
编号
信用卡
移动构造,而不是复制构造。当您使用此构造函数时,当对象传递到构造函数时,将有一个副本(或移动,如果是临时的),然后在初始化成员时有一个移动

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);

现在让我们考虑这个构造函数:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
Account(std::string number, float amount, CreditCard& creditCard)
  : number(number), amount(amount), creditCard(creditCard)
没错,这将涉及一份
信用卡
,因为它首先通过引用传递给构造函数。但是现在您不能将
const
对象传递给构造函数(因为引用是非
const
),也不能传递临时对象。例如,您不能这样做:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
Account account("something", 10.0f, CreditCard("12345",2,2015,1001));
现在让我们考虑一下:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
Account(std::string number, float amount, CreditCard&& creditCard)
  : number(number), amount(amount), creditCard(std::forward<CreditCard>(creditCard))
账户(标准::字符串编号、浮动金额、信用卡和信用卡)
:号码(数字)、金额(金额)、信用卡(标准::远期(信用卡))

这里显示了对右值引用和
std::forward
的误解。只有当要转发的对象被声明为某个推断类型的
T
时,才应该真正使用
std::forward
。在这里,
信用卡
并没有被推导出来(我假设),所以
std::forward
被错误地使用了。向上看。

首先是最重要的问题:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
<> P>有没有任何关于如何在C++中发送参数的最佳实践,因为我真的找到了,我们可以说,不是微不足道的< /P>
    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
如果您的函数需要修改要传递的原始对象,以便在调用返回后,调用方可以看到对该对象的修改,那么您应该通过左值引用传递:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
void foo(my_class& obj)
{
    // Modify obj here...
}
void foo(my_class const& obj)
{
    // Observe obj here
}
void foo(my_class obj) // One copy or one move here, but not working on
                       // the original object...
{
    // Working on obj...

    // Possibly move from obj if the result has to be stored somewhere...
}
如果函数不需要修改原始对象,也不需要创建原始对象的副本(换句话说,它只需要观察其状态),则应将左值引用传递给
常量

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
void foo(my_class& obj)
{
    // Modify obj here...
}
void foo(my_class const& obj)
{
    // Observe obj here
}
void foo(my_class obj) // One copy or one move here, but not working on
                       // the original object...
{
    // Working on obj...

    // Possibly move from obj if the result has to be stored somewhere...
}
这将允许您使用左值(左值是具有稳定标识的对象)和右值(例如,右值是临时值或调用
std::move()
后将要从中移动的对象)调用函数

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
人们还可以认为,对于基本类型或复制速度快的类型,如
int
bool
、或
char
,如果函数只需要观察值,则不需要通过引用传递,而且应该支持通过值传递。如果不需要引用语义,这是正确的,但是如果函数希望在某个地方存储指向同一输入对象的指针,以便将来读取该指针时可以看到在代码的其他部分中执行的值修改,该怎么办?在这种情况下,通过引用传递是正确的解决方案

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);

如果您的函数<强>不需要修改原始对象,但需要存储该对象的拷贝>(可能返回输入的转换结果而不改变输入),则可以考虑<强>值取值< /强>:

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
void foo(my_class& obj)
{
    // Modify obj here...
}
void foo(my_class const& obj)
{
    // Observe obj here
}
void foo(my_class obj) // One copy or one move here, but not working on
                       // the original object...
{
    // Working on obj...

    // Possibly move from obj if the result has to be stored somewhere...
}
调用上述函数将始终在传递左值时生成一个副本,在传递右值时生成一个移动副本。如果函数需要将该对象存储在某个位置,则可以从该对象执行额外的移动(例如,在
foo()
is的情况下)

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
<>强>在类型为<代码> MyOrthyBase<代码>对象的情况下,您可能会考虑重载<代码>脚注()/代码>,并为LValk提供一个版本(接受一个LValk引用到“代码> const ”和一个版本的RValk(接受rValk引用):

    CreditCard cc("12345",2,2015,1001);
    Account acc("asdasd",345, cc);
事实上,上述函数非常相似,您可以从中生成一个函数:
foo()
可以成为