Binary Search Tree without pass by reference Here is a code for BST that I have written , that does not use pass by reference. Help me to find flaws in its design. Also I do not like the function getReqNodes, can it be made more elegant.
#include &lt;iostream&gt;
using namespace std;

struct node {
    int data;
    node* left = nullptr;
    node* right = nullptr;
    node(int d , node *l = nullptr, node *r = nullptr){
        data = d;
        left = l;
        right = r;
    }
};
node* insertVal(node* n, int val) {
    if (n == nullptr) {
        n = new node(val);
        n-&gt;data = val;
        return n;
    }
    else if (val &lt; n-&gt;data){
        return new node(n-&gt;data, insertVal(n-&gt;left,val), n-&gt;right);
    }
    else if(val &gt; n-&gt;data) {
        return new node(n-&gt;data, n-&gt;left, insertVal(n-&gt;right, val)); 
    } 
    else{
        return new node(val, n-&gt;left, n-&gt;right);
    }
}
int minVal(node* n) {
    if (n == nullptr) return -10000;
    else if (n-&gt;left == nullptr) return n-&gt;data;
    else return minVal(n-&gt;left);
}


node* getReqNodes(node *t, node *q){
    if(q == nullptr){return t;}
    else{
        t = insertVal(t,q-&gt;data);
        t = getReqNodes(t,q-&gt;left);
        t = getReqNodes(t,q-&gt;right);
        return t;
    }
}

node* removeVal(node *n, int v){
    if (n == nullptr){return n;}
    else if(v &lt; n-&gt;data){
        return new node(n-&gt;data, removeVal(n-&gt;left,v), n-&gt;right);
    }
    else if(v &gt; n-&gt;data){
        return new node(n-&gt;data, n-&gt;left, removeVal(n-&gt;right, v));
    }
    else{
        node *j = n;
        //attaching right subtree to the left subtree
        node *p = getReqNodes(n-&gt;left, n-&gt;right);
        delete j;
        return p;
    }
}

void printTree(node* n) {
    if (n == nullptr) { return; }
    printTree(n-&gt;left);
    cout &lt;&lt; n-&gt;data &lt;&lt; &quot; &quot;;
    printTree(n-&gt;right);
}

int main() {
    node* p = nullptr;
    for(int i = 0; i &lt; 15; ++i){
        p = insertVal(p, rand()%15);
    }
    printTree(p);cout&lt;&lt;endl;cout&lt;&lt;endl;
    node *foo = removeVal(p, 149);
    printTree(foo);
    return 0;

}
General Observations
The code compiles and runs in Visual Studio 2019 on Windows 10.
The vertical spacing is inconsistent and could be improved.
The code could be reusable if the Binary Search Tree was made into a class.
The unit testing in main could be more effective if know values were used first and then a second test with random number generated. The test of removeVal() currently only tests a value that is never in the BST, the function does work because I changed the value in the test.
Avoid using namespace std;
If you are coding professionally you probably should get out of the habit of using the using namespace std; statement. The code will more clearly define where cout and other identifiers are coming from (std::cin, std::cout). As you start using namespaces in your code it is better to identify where each function comes from because there may be function name collisions from different namespaces. The identifiercout you may override within your own classes, and you may override the operator &lt;&lt; in your own classes as well. This stack overflow question discusses this in more detail.
Function and Variable Naming
Generally the function names are fairly good, there is one exception, it isn't clear to me from the name what getReqNodes() is supposed to do.  In main it might be better to have a variable called bst or root rather than p.
Random Number Generation
It would be better to use C++ random number generators rather than the old C library function rand() function, see EDIT 2 in the first answer to this stack overflow question. Currently the random number generator is not random because it is never seeded with a value by calling srand().
One Statement Per Line
The code contains multiple lines where there is more than one statement such as:
    printTree(p); cout &lt;&lt; endl; cout &lt;&lt; endl;

This makes the code harder to read, understand and maintain, always remember that you may not be the only person that needs to edit the code.
There are 2 other issues with that line, that std::endl flushes the output which affects the performance of the program so using:
    std::cout &lt;&lt; &quot;\n&quot;;

might be a better option. The second is that if a string such as &quot;\n&quot; is used then the string &quot;\n\n&quot; can be used to output 2 new lines, decreasing the number of statements necessary, although this is also possible:
    std::cout &lt;&lt; std::endl &lt;&lt; std::endl;