通过值或常量引用传递给函数?

Posted

技术标签:

【中文标题】通过值或常量引用传递给函数?【英文标题】:Pass by value or const reference to function? 【发布时间】:2015-03-28 01:54:03 【问题描述】:

我应该通过值还是通过引用一个函数来传递std::string。此函数将这些值存储在类的成员变量中。

在传递值或引用时,我总是感到困惑。请清除我对此的困惑。

代码如下:

class DataStore 
public:
    void addFile(const string& filename, const set< std::string>& filePaths)
      
        if (dataStoreMap.insert(make_pair(filename, filePaths)).second)
        
            cout << "Data Added" <<endl;
        
        else
        
            cout << "Data not Added" << endl;
        
    
private:
    // member variable
    map < string, set < string >  > dataStoreMap;
;

我应该像这样声明函数吗:

void addFile(const string& filename, const set< std::string>& filePaths)

void addFile(const string filename, const set< std::string> filePaths)

两者都给出相同的结果。如果有任何关于内存分配或性能的问题。

来自cpp 类的上述函数调用。

DataStore ds;
set<string> setFileDirectory "1", "2", "3", "4", "6", "5" ;
ds.addFile("file.txt", setFileDirectory);

setFileDirectory.erase(setFileDirectory.begin(), setFileDirectory.end());
setFileDirectory.insert( "1", "2", "3", "4", "5", "6" );
ds.addFile("demo.txt", setFileDirectory);

任何详细的解释将不胜感激。

谢谢

【问题讨论】:

非常感谢您的回复。我明白你的意思,但是当我必须使用 value 或 ref 时。这仍然让我感到困惑。在这里,我将在地图中存储值,所以按值传递是好事吗?还是通过参考? 你的问题是按值传递和按引用传递的区别是什么? @Namfuak :何时使用传递引用或传递值之间的混淆。 【参考方案1】:

当你有一个输入参数,即被函数观察并且没有修改的东西,考虑通过传递它const 引用 (const &amp;),以避免无用的深拷贝(可能需要动态内存分配等)

void addFile(const std::string& filename, 
             const std::set<std::string>& filePaths)

附言 当然,如果你传递的参数复制起来很便宜,比如ints,你可以只传递值:)

【讨论】:

非常感谢您的回复。我明白你的意思,但是当我必须使用 value 或 ref 时。这仍然让我感到困惑。在这里我要将值存储在地图中,所以按值传递是好事吗?还是通过参考? @Sam_k:请保持两个方面的区别:您在地图(或其他容器)中存储的内容,以及作为参数传递给函数的内容。我的回答侧重于作为参数传递的内容,我不会在此评论中重复我的回答。相反,关于将内容存储在容器中,通常存储值是一个不错的选择:它对值进行深度复制,因此它们“物理地”包含在容器中,并与其他外部上下文解耦(这也简化了所有权、生命周期管理等)。【参考方案2】:

第一个具有“更好”的性能,因为第二个在通过之前复制了string。由于您没有修改string,因此在调用函数中传递对实际字符串的引用而不是进行复制没有缺点,并且复制引用所需的内存比string 少。也就是说,如果您从不放弃 string 变量上的 const 说明符,编译器最终可能会同等对待它们。这种差异对大参数更有用,例如,如果您的 filepaths 变量有几千个元素,则通过引用而不是值传递它可能会有非常明显的差异。

相关:Is it better in C++ to pass by value or pass by constant reference?

【讨论】:

【参考方案3】:

如果你的容器集很大并且传递给函数的字符串比较小,我可以使用如下:

void addFile(const string filename, const set< std::string> & filePaths)

【讨论】:

insert 返回一个pair&lt;iterator, bool&gt;,如果插入成功,则第二个元素为true,否则为false,这似乎是他打算检查的内容。为什么你认为它是错误的? 没错。我正在检查插入函数返回的真假【参考方案4】:

首先,您应该永远通过 const 传递参数,因为这几乎没有任何理由。按值传递已经确保您不能在调用站点更改变量,因为它是复制的

现在,关于按值或引用传递参数的问题仍然存在。答案比预期的要复杂。 Stack Overflow 上有很多很好的答案。

简而言之,当将潜在的大对象(如 std::vectorstd::string)传递给函数时,请使用以下惯用准则:

在传递观察时(只读)通过引用传递给const。 在传递要保留副本的参数时(所谓的 sink 参数),也可以通过引用传递给 const。如果传递的对象是可移动的,您还可以通过 rvalue reference (T&amp;&amp;) 添加一个重载,以进行优化。

相关信息:

What's the difference between passing by reference vs. passing by value? Is it better in C++ to pass by value or pass by constant reference? Dave Abrahams - Want Speed? Pass by Value What are move semantics? Why is value taking setter member functions not recommended in Herb Sutter's CppCon 2014 talk (Back to Basics: Modern C++ Style)?

【讨论】:

"这几乎没有任何原因(内置类型除外)" 内置类型的例外是什么? @NeilKirk Well IMO 有时使用例如const int 用于您不想在函数内部修改的数字(它只会为实现者增加价值)。我仍然删除了那部分,因为我的论点有点弱:)

以上是关于通过值或常量引用传递给函数?的主要内容,如果未能解决你的问题,请参考以下文章

函数/变量范围(通过值或引用传递?)

通过指针或引用将映射传递给函数?

构造函数的最佳形式?通过值或引用传递?

C++ 是不是通过值或引用传递对象?

传递常量是通过引用自动传递的吗?

按值、常量值、引用或常量引用传递非 POD 类型