我是c++编程的新手,但我有Java的经验。我需要关于如何在c++中传递对象到函数的指导。
我需要传递指针,引用,或非指针和非引用值吗?我记得在Java中不存在这样的问题,因为我们只传递包含对象引用的变量。
如果你能解释一下在哪里使用这些选项,那就太好了。
我是c++编程的新手,但我有Java的经验。我需要关于如何在c++中传递对象到函数的指导。
我需要传递指针,引用,或非指针和非引用值吗?我记得在Java中不存在这样的问题,因为我们只传递包含对象引用的变量。
如果你能解释一下在哪里使用这些选项,那就太好了。
当前回答
有几种情况需要考虑。
参数修改("out"和"in/out"参数)
void modifies(T ¶m);
// vs
void modifies(T *param);
这个例子主要是关于样式:你想让代码看起来像call(obj)还是call(&obj)?但是,有两点是有区别的:下面的可选情况,以及在重载操作符时希望使用引用。
...和可选的
void modifies(T *param=0); // default value optional, too
// vs
void modifies();
void modifies(T ¶m);
参数未修改
void uses(T const ¶m);
// vs
void uses(T param);
这是一个有趣的例子。经验法则是“容易复制”的类型是通过值传递的-这些通常是小类型(但不总是)-而其他类型是通过const ref传递的。然而,如果你需要在你的函数中进行复制,你应该通过值传递。(是的,这暴露了一些实现细节。这是c++。)
...和可选的
void uses(T const *param=0); // default value optional, too
// vs
void uses();
void uses(T const ¶m); // or optional(T param)
所有情况之间的差异都很小,所以选择任何让你的生活更轻松的情况。
Const by value是一个实现细节
void f(T);
void f(T const);
这些声明实际上是完全相同的函数!当按值传递时,const纯粹是一个实现细节。试试吧:
void f(int);
void f(int const) { /* implements above function, not an overload */ }
typedef void NC(int); // typedefing function types
typedef void C(int const);
NC *nc = &f; // nc is a function pointer
C *c = nc; // C and NC are identical types
其他回答
将对象作为参数传递给函数有三种方法:
通过引用传递 按值传递 在参数中添加常数
看下面的例子:
class Sample
{
public:
int *ptr;
int mVar;
Sample(int i)
{
mVar = 4;
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value of the pointer is " << *ptr << endl
<< "The value of the variable is " << mVar;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
char ch;
cin >> ch;
}
输出:
说我在someFunc 指针的值为-17891602 变量的值是4
有几种情况需要考虑。
参数修改("out"和"in/out"参数)
void modifies(T ¶m);
// vs
void modifies(T *param);
这个例子主要是关于样式:你想让代码看起来像call(obj)还是call(&obj)?但是,有两点是有区别的:下面的可选情况,以及在重载操作符时希望使用引用。
...和可选的
void modifies(T *param=0); // default value optional, too
// vs
void modifies();
void modifies(T ¶m);
参数未修改
void uses(T const ¶m);
// vs
void uses(T param);
这是一个有趣的例子。经验法则是“容易复制”的类型是通过值传递的-这些通常是小类型(但不总是)-而其他类型是通过const ref传递的。然而,如果你需要在你的函数中进行复制,你应该通过值传递。(是的,这暴露了一些实现细节。这是c++。)
...和可选的
void uses(T const *param=0); // default value optional, too
// vs
void uses();
void uses(T const ¶m); // or optional(T param)
所有情况之间的差异都很小,所以选择任何让你的生活更轻松的情况。
Const by value是一个实现细节
void f(T);
void f(T const);
这些声明实际上是完全相同的函数!当按值传递时,const纯粹是一个实现细节。试试吧:
void f(int);
void f(int const) { /* implements above function, not an overload */ }
typedef void NC(int); // typedefing function types
typedef void C(int const);
NC *nc = &f; // nc is a function pointer
C *c = nc; // C and NC are identical types
Since no one mentioned I am adding on it, When you pass a object to a function in c++ the default copy constructor of the object is called if you dont have one which creates a clone of the object and then pass it to the method, so when you change the object values that will reflect on the copy of the object instead of the original object, that is the problem in c++, So if you make all the class attributes to be pointers, then the copy constructors will copy the addresses of the pointer attributes , so when the method invocations on the object which manipulates the values stored in pointer attributes addresses, the changes also reflect in the original object which is passed as a parameter, so this can behave same a Java but dont forget that all your class attributes must be pointers, also you should change the values of pointers, will be much clear with code explanation.
Class CPlusPlusJavaFunctionality {
public:
CPlusPlusJavaFunctionality(){
attribute = new int;
*attribute = value;
}
void setValue(int value){
*attribute = value;
}
void getValue(){
return *attribute;
}
~ CPlusPlusJavaFuncitonality(){
delete(attribute);
}
private:
int *attribute;
}
void changeObjectAttribute(CPlusPlusJavaFunctionality obj, int value){
int* prt = obj.attribute;
*ptr = value;
}
int main(){
CPlusPlusJavaFunctionality obj;
obj.setValue(10);
cout<< obj.getValue(); //output: 10
changeObjectAttribute(obj, 15);
cout<< obj.getValue(); //output: 15
}
但这不是一个好主意,因为你最终会编写大量涉及指针的代码,指针很容易发生内存泄漏,并且不要忘记调用析构函数。为了避免这种情况,c++有复制构造函数,当包含指针的对象被传递给函数参数时,你将创建新的内存,这将停止操作其他对象的数据,Java是通过值和值是引用传递的,所以它不需要复制构造函数。
c++和Java在调用约定方面有一些不同。在c++中,从技术上讲只有两种约定:值传递和引用传递,一些文献还包括第三种指针传递约定(实际上是指针类型的值传递)。在此基础上,您可以向实参类型添加const-ness,从而增强语义。
通过引用传递
通过引用传递意味着函数将在概念上接收您的对象实例,而不是它的副本。引用在概念上是调用上下文中使用的对象的别名,不能为空。在函数内部执行的所有操作都适用于函数外部的对象。这个约定在Java或C中是不可用的。
按值传递(和按指针传递)
编译器将在调用上下文中生成对象的副本,并在函数中使用该副本。在函数内部执行的所有操作都是对副本执行的,而不是外部元素。这是Java中基本类型的约定。
An special version of it is passing a pointer (address-of the object) into a function. The function receives the pointer, and any and all operations applied to the pointer itself are applied to the copy (pointer), on the other hand, operations applied to the dereferenced pointer will apply to the object instance at that memory location, so the function can have side effects. The effect of using pass-by-value of a pointer to the object will allow the internal function to modify external values, as with pass-by-reference and will also allow for optional values (pass a null pointer).
这是C语言中当函数需要修改外部变量时使用的约定,也是Java引用类型中使用的约定:引用被复制,但引用对象是相同的:对引用/指针的更改在函数外部是不可见的,但对指向内存的更改是可见的。
在方程中加入const
In C++ you can assign constant-ness to objects when defining variables, pointers and references at different levels. You can declare a variable to be constant, you can declare a reference to a constant instance, and you can define all pointers to constant objects, constant pointers to mutable objects and constant pointers to constant elements. Conversely in Java you can only define one level of constant-ness (final keyword): that of the variable (instance for primitive types, reference for reference types), but you cannot define a reference to an immutable element (unless the class itself is immutable).
This is extensively used in C++ calling conventions. When the objects are small you can pass the object by value. The compiler will generate a copy, but that copy is not an expensive operation. For any other type, if the function will not change the object, you can pass a reference to a constant instance (usually called constant reference) of the type. This will not copy the object, but pass it into the function. But at the same time the compiler will guarantee that the object is not changed inside the function.
经验法则
以下是一些需要遵循的基本规则:
对基元类型更倾向于值传递 对于其他类型,建议使用对常量的引用的引用传递 如果函数需要修改实参,则使用引用传递 如果参数是可选的,则使用pass-by-pointer(如果不应修改可选值,则为常量)
There are other small deviations from these rules, the first of which is handling ownership of an object. When an object is dynamically allocated with new, it must be deallocated with delete (or the [] versions thereof). The object or function that is responsible for the destruction of the object is considered the owner of the resource. When a dynamically allocated object is created in a piece of code, but the ownership is transfered to a different element it is usually done with pass-by-pointer semantics, or if possible with smart pointers.
边注
强调c++和Java引用之间区别的重要性是很重要的。在c++中,引用在概念上是对象的实例,而不是对象的访问器。最简单的例子是实现交换函数:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
上面的swap函数通过使用引用来改变它的两个参数。Java中最接近的代码:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
Java版本的代码将在内部修改引用的副本,但不会在外部修改实际的对象。Java引用是没有指针算术的C指针,它通过值传递给函数。
下面是c++中传递参数/形参给函数的方法。
1. 的价值。
// passing parameters by value . . .
void foo(int x)
{
x = 6;
}
2. 通过引用传递。
// passing parameters by reference . . .
void foo(const int &x) // x is a const reference
{
x = 6;
}
// passing parameters by const reference . . .
void foo(const int &x) // x is a const reference
{
x = 6; // compile error: a const reference cannot have its value changed!
}
3.通过对象。
class abc
{
display()
{
cout<<"Class abc";
}
}
// pass object by value
void show(abc S)
{
cout<<S.display();
}
// pass object by reference
void show(abc& S)
{
cout<<S.display();
}