假设我有以下内容:
class MyClass
{
// ...
}
void doSomething (MyClass instance)
{
// Is instance passed by reference or by value (copied)?
}
void main ()
{
MyClass instance = MyClass();
doSomething(instance);
}
在doSomething()
instance
是否通过引用传递?或者类是否在内存中重复?或其他什么?
答案 0 :(得分:5)
这是通过值传递的
void doSomething (MyClass instance)
这是通过引用传递的
void doSomething (MyClass& instance)
这是由const引用传递的
void doSomething (const MyClass& instance)
同样MyClass
不需要通过赋值构造。
所以:
MyClass mc=MyClass();
实际上与:
相同MyClass mc; //no parens needed for default constructor (no args).
编辑: 这是通过const引用传递给const函数,const函数可以在const对象上调用,因为它保证不修改对象状态。
void doSomething (const MyClass& instance) const
与许多不太严格的语言不同,Const正确性被认为是C ++中的良好实践。
见我:
答案 1 :(得分:1)
如果没有明确说明,则不是参考。这是有价值的。
以下原型表示通过引用传递的参数:
void doSomething (MyClass& instance)
{
// Is instance passed by reference or by value (copied)?
// In this case, by reference
}
实际上,在您的情况下,很可能会创建一个新对象。我说的最有可能的原因是,只要可观察的行为是相同的,它也可能不是。但是,理论上,是的,创建了一个在函数内部使用的新对象。
通过调用作为参数传递的对象的复制构造函数来创建新对象。如果尚未定义复制构造函数,则编译器会生成一个默认值,它会执行浅表复制。
答案 2 :(得分:1)
是的,它被复制了。
当您致电doSomething
时,会调用MyClass
复制构造函数来创建新实例。
此实例将在doSomething
函数的持续时间内保留。当函数结束时,将为此实例调用MyClass
析构函数。
(请注意,如果您还没有编写复制构造函数,默认情况下会为您创建一个。)
因此,如果添加显式复制构造函数和析构函数:
class MyClass
{
public:
MyClass()
{
std::cout << "MyClass constructor" << std::endl;
}
MyClass(const MyClass& other)
{
std::cout << "MyClass copy constructor" << std::endl;
}
MyClass::~MyClass()
{
std::cout << "MyClass destructor" << std::endl;
}
}
void doSomething (MyClass instance)
{
std::cout << "doSomething method";
}
void main ()
{
MyClass instance = MyClass();
std::cout << "invoking doSomething" << std::endl;
doSomething(instance);
std::cout << "returned from doSomething" << std::endl;
}
这将输出以下内容:
答案 3 :(得分:1)
它被复制在堆栈上以便传递给函数。如果您的类已达到一定量的字节,这可能非常昂贵,因为每个实例变量必须在堆栈上布局。在这种情况下,类的行为与常规c结构的行为不同。
所以假设你在课堂上有2个整数(我假设是32位系统)
class A {
int a;
int b;
};
当你在main中声明它时,堆栈指针会下降8个字节。 如果您调用your_function(A),C也必须将布局类复制到堆栈中,以便your_function在调用后可以访问它。这意味着堆栈指针再次下降8个字节,值从旧值写入并调用函数。
有2个实例变量,这不是什么大问题。但是图像你有一个持有结构的类,可以说20个整数+一个虚拟表?比我可以是一个非常昂贵的操作。如果通过指针传递,则堆栈指针必须仅下降4个字节,复制其中的类的地址并调用该函数。当然更便宜。
你可以自己尝试。只需更改函数中的某个实例变量,然后在函数返回后检查,如果第一个类具有新值或函数调用之前的值。这应该给你答案。
在任何情况下,如果这是您想要的,您应该实现一个复制构造函数来处理如何复制变量。