价值转换与参考演员

时间:2018-05-06 16:44:34

标签: c++ c++11

价值参考演员之间有什么区别?为什么他们中的一个调用转换(也就是创建新对象)而其他没有?在rhs上使用cast的注意事项是什么?

假设派生。为什么那些实际上不会转换为 Base

*this = (Base&) rhs
(Base)* this = rhs

你能用简单的例子来表示吗?

2 个答案:

答案 0 :(得分:3)

Value cast creates a new value from an existing one; reference cast creates a new reference to the same existing value.

Reference cast neither changes the content of an existing object nor creates a new one; it is restricted to changing the interpretation of the value that is already there. Value casting, on the other hand, can make a new object from an existing one, so it has fewer restrictions.

For example, if you have an routes.rb and you want a value or a reference of type update, value cast is going to work, while reference casting is going to fail:

unsigned char

int is unsigned char orig = 'x'; int v(orig); // Works int &r(orig); // Does not work , I want to assign all inherited and non-inherited stuff from rhs into Derived

Then you need to cast both sides to rhs, or add an assignment operator to Base that takes a Base as an argument. Here is an example of casting on both sides (may be hard to understand by other programmers reading your code)

Derived

Running the code below

const Base&

produces the following printout:

struct Base {
    int x;
    Base(int x) : x(x) {}
};
struct Derived1 : public Base {
    Derived1(int x) : Base(x) {}
};
struct Derived2 : public Base {
    Derived2(int x) : Base(x) {}
};

As you can see, the assignment Derived1 d1(5); Derived2 d2(10); cout << d1.x << " " << d2.x << endl; ((Base&)d1) = (Base&)d2; cout << d1.x << " " << d2.x << endl; copied the content of 5 10 10 10 's ((Base&)d1) = (Base&)d2 portion into d2's Base portion (demo).

答案 1 :(得分:2)

What is the difference between value cast and reference cast?

Value casts convert an object to the value:

struct GraphNode
{
    char ID;
    std::string name;
    int inNodes = 0;
    int outNodes = 0;
    std::vector<std::pair<GraphNode*, int>> connection;
    int  connections = 0;
};

Reference casts convert an object to a reference:

#include "Graph.h"

std::vector<GraphNode*> _graph;
int openNode = 0;

//Obligatory constructor
void Graph()
{

}

void shortestPath(char fromNode, char toNode)
{
    bool known[openNode];
    int distance[openNode];
    GraphNode*  previous[openNode];
    int numbChecked = 0;


    for (int i = 0; i < openNode; i++)
    {
        known[i] = false;
        distance[i] = 999999;
        previous[i] = nullptr;
    }

    distance[findNode(fromNode)] = 0;

    while (numbChecked < openNode)
    {
        int smallestUnknown = 9999999;
        int locationOfSmall = 0;
        for (int i = 0; i < openNode; i++)
        {
            if (known[i] == false && distance[i] < smallestUnknown)
            {
                smallestUnknown = distance[i];
                locationOfSmall = i;
            }
        }

        if (distance[locationOfSmall] == 0)
        {
            previous[locationOfSmall] = nullptr;
        }

        known[locationOfSmall] = true;
        numbChecked++;

        if (_graph[locationOfSmall]->outNodes > 0)
        {
            for (int i = 0; i < _graph[locationOfSmall]->outNodes; i++)
            {
                int newDistanceLocation = findNode(_graph[locationOfSmall]->connection[i].first->ID);
                if (known[newDistanceLocation] == false && (distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second) < distance[newDistanceLocation])
                {
                    distance[newDistanceLocation] = distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second;
                    previous[newDistanceLocation] = _graph[locationOfSmall];
                }
            }
        }
    }

    int destination = findNode(toNode);
    std::string output;
    std::string charTransfer;
    charTransfer = toNode;
    output = charTransfer;

    while (previous[destination] != nullptr)
    {
        destination = findNode(previous[destination]->ID);
        charTransfer = _graph[destination]->ID;
        output = charTransfer + "->" + output;
    }

    if (_graph[destination]->ID != fromNode)
    {
        std::cout << "The nodes are not connected." << std::endl;
    }
    else
    {
        std::cout << "The path is: " << output << std::endl;
        std::cout << "The distance is: " << distance[findNode(toNode)] << std::endl;
    }

}

Just because the conversion can be done implicitly in char i = 'a'; int k = static_cast<int>(i); // Prefer C++ casts to C casts doesn't mean it doesn't happen.

Why one of them invokes conversion (aka creating new object) and other doesn't?

If you write char i = 'a'; int &k = static_cast<int&>(i); , there are 2 things that can happen:

1) A pointer is created pointing to int &k = i (references are hidden pointers). Then this hidden pointer gets assigned to int &x = static_cast<int&>(i), and i behaves as a reference of x.

2) Usually, the compiler optimizes away this reference, and simply considers x an alias of i. Therefore no variable is instantiated.

In the former case, a new object is created.

However, if you write:

x

there is no instantiation, just a copy of the memory from i to char c = 'a'; int i = static_cast<int> (c); .

Why those will not actually cast to Base?

c

You cannot assign the base object to a derived object, only the opposite. This will most likely overwrite the fields of the base object to the derived object's.

i

There is no point in castling an l-value. This is equivalent to:

*this = (Base&) rhs

What are caveats of using casting on rhs?

I don't think there is anything wrong with casting, as long as they do not decrease readability.