class mystring {
 friend ostream& operator<<(ostream &out, const mystring ss) {
        out << ss.s;
        return out;
    }
private:
    string s;
public:
    mystring(const char ss[]) {
        cout << "constructing mystring : " << ss << endl;
        s = ss;
    }
};

void outputStringByRef(const mystring &ss) {
 cout << "outputString(const string& ) " << ss << endl;
}

void outputStringByVal(const mystring ss) {
 cout << "outputString(const string ) " << ss << endl;
}

int main(void) {
    outputStringByRef("string by reference");
    outputStringByVal("string by value");
    outputStringByRef(mystring("string by reference explict call mystring consructor"));
    outputStringByVal(mystring("string by value explict call mystring constructor"));
} ///:~

考虑到上述示例,我们无法修改的通按引用变量,我们也不可以修改的每个方法通过噪声值variable.The输出的是same.Since在这两个方法之间没有区别,为什么C ++支持这两种方法?

感谢。

有帮助吗?

解决方案

有两者之间的差。考虑以下几点:

#include <iostream>
#include <string>
using std::string;

string g_value;

void callback() {
    g_value = "blue";
}

void ProcessStringByRef(const string &s) {
    callback();
    std::cout << s << "\n";
}

void ProcessStringByValue(const string s) {
    callback();
    std::cout << s << "\n";
}

int main() {
    g_value = "red";
    ProcessStringByValue(g_value);
    g_value = "red";
    ProcessStringByRef(g_value);
}

输出:

red
blue

仅仅因为一个参考是在函数内部常量,并不意味着该referand不能通过其他参考被修改(的具有多个引用或指针给它的一个对象被称为“混叠”的情形)。因此,存在通过const引用,并通过一个常数值之间的不同 - 在参考的情况下,该呼叫由后的对象可能会改变。在该值的情况下,被叫方有一个专用副本,它也不会改变。

由于他们做不同的事情,C ++让你选择你想要的。

有绩效的后果无论哪种方式 - 当你路过值,副本要作出,它的价格。但是,编译器就知道,只有你的函数都不可能有该副本,这可能会允许其他的优化的任何引用。 ProcessStringByRef无法加载字符串的内容打印到callback()又回来了。 ProcessStringByValue可以,如果编译器认为这样做比较快。

通常你所关心的副本,而不是指令执行顺序,因为通常情况下副本的方式更加昂贵。所以通常情况下,你通过引用传递,其中有可能是不平凡的复制对象。但走样的可能性,有时有表现的确严重后果,防止即使没有走样实际发生一定的优化。这就是为什么“严格别名规则”的存在,并在C99的restrict关键字。

其他提示

f(const string&)通过const参考取串:fis直接通过引用传递的字符串对象上操作:不存在所涉及的副本。 const防止修改原始对象虽然。

f(const string)采用一个字符串值,这意味着f给出原始字符串的副本。即使跌落const,按值传递时,对字符串中的任何修改都将丢失时f回报。

我并不确切地知道你的“为什么C ++支持这两种方法?”的意思。它适用只是一般的重载规则。

f(string s)传值字符串s,换句话说,它创建一个副本,并与传递的字符串的值进行初始化。在副本中的任何改变,都不会传播给你传递给调用函数的原始字符串。 在f(const string s) const为多余的,因为不能改变无论如何原始值。

f(const string& s)不是字符串不被复制,但传递到它的一个参考。当你有一个大的对象,这样的“传递的价值”能够产生的开销这通常是(这就是为什么C ++支持这两种方法)。按引用传递意味着你可以改变你通过“大”对象的值,但由于限定符const,你不能修改它。这是一种“保护”。

你的对象可能包含一个可变构件,其可甚至与被修改const引用

使用outputStringByRef你必须确保变量你传递的引用,仍然活着,并没有改变,只要outputStringByRef需要它。与outputStringByVal您可以通过死亡或走出范围的变量和函数具有复制仍未确定。

有(几乎)在能够给该函数内修改字符串方面没有差异。但是,有在被传递什么样的条件有很大的区别。所述const mystring &ss重载采用常量引用的字符串。虽然不能修改它,它正在处理相同的内存。如果字符串长度这可能是一个很大的因素(假设这个字符串没有使用复制来实现-on写)。所述const mystring ss形式使字符串的副本,所以不同的存储器将得到解决。

其实const mystring &ss形式的可能的修改字符串,如果使用了const_cast<mystring&> - 虽然我不建议在这里

假设你要打印不能被复制的对象:

Thread th;
// ...
cout << th; // print out informations...

在参考版本不会复制线程,但将采取th的地址,并创建一个别名给它。另一版本将尝试复制由值传递当线程 - 但复制可能不适用于这样的目的是senseful(?会有一个额外的螺纹然后)

它可以帮助你思考的的复制对象的作为的克隆对象的。复制th以上C ++并不仅仅意味着有另一个手柄相同的对象在Java中 - 它意味着隐式克隆对象表示,有它的整个副本。所以,问题是类似“为什么Java支持的引用既Object.clone和复制?” - 都有不同的目的。

再有就是性能的问题也一样,毕竟。你不想给每一位你传递的资源饥饿物体周围的东西一次复制。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top