了解在C ++中通过引用传递地址

时间:2015-10-30 01:22:06

标签: c++ pointers reference

我写了一段简单的C ++代码来通过引用传递地址。

我将一个变量(比如说y)和一个数组(比如说arr)的地址传递给一个类。 arr y 都将在类中修改。我想在main()中修改值。

请在下面的代码中找到我的问题,因为这样更容易。感谢。

#include <iostream>
using namespace std;

class A
{
public:
    // Assign  values to the array and increment _x.
    void increment()
    {
        (*_x)++;
        (*_arr)[0] = 1; // Q1. Is it safe to directly access the array like this.
        (*_arr)[1] = 2; //     Don't I have to allocate memory to the array ?
        (*_arr)[2] = 3;
    }

    // Get the address of the Variable that is passed in main. x will now have &y2.
    A (int* &arr, int* &x):
        _x(x)
    {
        *_arr = arr;
    }

private:
    int* _x;
    int** _arr;
};

int main()
{
    int y = 9;
    int arr[5];

    int *pY = &y;
    int *pArr = arr;

    A *obj1 = new A(pArr, pY);

    // This gives a compile time error. warning: initialization of non-const reference int *&' from rvalue `int *'
    // A *obj1 = new A(&y);   <-- Q2. Why does this give a Compile Time Error ?
    obj1->increment();

    cout << "y : " << y << endl;
    cout << "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << endl;
    cout << endl;
    return 0;
}
  1. 在A :: increment()函数中,我直接为数组赋值而没有 分配内存。这样做安全吗?如果没有,我该如何分配内存呢? 我仍然可以在main()?
  2. 中获取修改后的数组值
  3. 为什么在我传递给A的构造函数时会出现编译时错误?
  4. 提前致谢。

4 个答案:

答案 0 :(得分:4)

问题1

  

在A :: increment()函数中,我直接将值赋给数组而不分配内存。这样做安全吗?如果没有,我如何分配内存,以便仍然可以在main()?

中获取修改后的数组值

<强>答案

是的,这是安全的。

问题2

  

为什么在我传递给A&#; s构造函数时会出现编译时错误?

<强>答案

<div> <label>Enter a different Value: </label><input id="txtOne" /> <input type="button" id="btnOne" value="Set Data" onclick="btn1Click(this);" /> </div> <script type="text/javascript"> var btn1 = document.getElementById('btnOne'); var input1 = document.getElementById('txtOne'); function btn1Click(e) { localStorage.dataItem = input1.value; } </script> 不是左值。因此,在参数类型为&y的情况下不能使用它。

发布代码中的问题

int*&

这是一个问题,因为 *_arr = arr; 尚未初始化为指向有效内存。在_arr尚未初始化时使用*_arr会导致未定义的行为。您可以将_arr的类型更改为:

_arr

并简化您的代码。

int* _arr;

不改变class A { public: // Assign values to the array and increment _x. void increment() { (*_x)++; _arr[0] = 1; // Q1. Is it safe to directly access the array like this. _arr[1] = 2; // Don't I have to allocate memory to the array ? _arr[2] = 3; } // Get the address of the Variable that is passed in main. x will now have &y2. A (int* &arr, int* &x): _x(x), _arr(arr) { } private: int* _x; int* _arr; }; 中的任何内容。

答案 1 :(得分:1)

这很少是你想要的; T**通常是一个数组数组,或者是您想要在调用者范围内修改的指针值。但是,这似乎都不是你在这里做的。

当且仅当*_arr[0]已初始化为非const数组数组时才可以修改_arr(*_arr)[0]当且仅当它已初始化为非{指向非const数组的指针。这里似乎都不是这种情况,但如果是这样的话,你可能想要明确地给出数组长度。

在此示例中,&y是常量。您无法修改它,因此您不能将其作为非const变量传递。您可以声明指针int *py = &y;并传递它。但请考虑这是否是你想要做的。

顺便说一下,使用以下划线开头的标识符并不好,因为按照标准,它们是为编译器保留使用的。

答案 2 :(得分:1)

你应该告诉我们你要做什么。在我看来,没有充分理由,在C ++中使用原始指针/数组和裸新/(缺少?)删除是无意义的。我还要注意,对于类成员使用_prefix不是一种好的做法。通常,前导_用于std实现。如果你坚持使用m_prefix,我建议你使用它。为什么你给_arr类型int **?是应该是2D阵列?另外,通过引用传递指针确实没有意义。指针已经是一个指针,如果你知道我的意思,只需传递指针。

我只是假设你这样做是为了理解手动内存管理或指针算术或者 - 等等,对:告诉我们你要做什么以及为什么。然而,我不明白你的课程是什么:

#include <iostream>

void increment(int& x, int *arr, int sz)
{
    ++x;
    for (int i = 0; i != sz; ++i)
    {
        // this just numbers the values respectively (starting at 1)
        arr[i] = i + 1;
    }
}

int main()
{
    using namespace std;

    int y = 9;
    const int sz = 5;
    int arr[sz];

    increment(y, arr, sz);

    cout << "y : " << y << '\n'
         << "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
}

回答你的问题: 2.首先要做的是:我没有看到任何只需要一个参数的构造函数。

  1. 阅读&#34;未定义的行为(UB)&#34;起点:What are all the common undefined behaviours that a C++ programmer should know about?
  2. 我不能重复,以至于我不明白你的目标是什么,这使得很难给出可靠的建议。

    我试着修复你的版本..它仍然很可怕......我强烈建议你阅读std :: array,std :: vector。也许在指针,C风格的数组以及如何将C风格的数组作为函数参数传递(注意:对于常规的C ++编程,你通常不会这样做/使用它。)

    #include <iostream>
    
    class A {
    public:
        // Assign  values to the array and increment m_x.
        void increment()
        {
            ++(*m_x);
            m_arr[0] = 1;
            m_arr[1] = 2;
            m_arr[2] = 3;
         }
    
        A (int* arr, int* x):
            m_x(x), m_arr(arr)
        {
        }
    
    private:
        int* m_x;
        int* m_arr;
    };
    
    int main()
    {
        using namespace std;
    
        int y = 9;
        int arr[5];
    
        A obj1(arr, &y);
        obj1.increment();
        cout << "y : " << y << '\n'
                 << "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
    
        A obj2(arr, &y);
        obj2.increment();
        cout << "y : " << y << '\n'
             << "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
    }
    

    你还应该读取非指针/引用及其差异

    我实际上是想让您的编程生活更轻松。对不起,答案很长。

答案 3 :(得分:0)

回答你的第一个问题

  

在A :: increment()函数中,我直接为其赋值   数组没有分配内存。这样做安全吗?如果没有,我该怎么办   分配内存,以便我仍然可以获取修改后的数组值   main()?

你在main()中的行

中分配了内存
int arr[5];

在类设计方面,您定义了类构造函数以接受引用参数,这意味着必须将现有的int *传递给每个参数:

A (int* &arr, int* &x)

并在调用构造函数时执行此操作:

A *obj1 = new A(pArr, pY);

所以在这个程序中,你正在做的是安全的。如果你希望在另一个上下文中使用这个类,那么潜在的危险就是你的main()中的arr数组包含少于3个元素,因为你的increment()函数初始化了数组的第三个元素。

回答你的第二个问题

  

为什么在我传递给A&#; s构造函数时会出现编译时错误?

在原始构造函数中,

 // Get the address of the Variable that is passed in main. x will now have &y2.
 A (int* &arr, int* &x):
     _x(x)
 {
     *_arr = arr;
 }

您在初始化之前解除引用_arr。解决这个问题的一种方法是:

    // Get the address of the Variable that is passed in main. x will now have &y2.
    A (int* &arr, int* &x):
        _x(x)
    {
        _arr = new (int*);
        *_arr = arr;
    }

    // Destructor
    ~A ()
    {
        delete _arr;
    }

另外,您还可以在main()中使用new。每当您使用new时,您还应该使用delete来避免内存泄漏。因此,在程序的底部,在return语句之前,添加以下内容:

delete obj1;