【问题标题】:Force C++ class instances to change member value when copied or assigned强制 C++ 类实例在复制或分配时更改成员值
【发布时间】:2013-04-07 02:52:53
【问题描述】:

我有一个名为Solution 的类定义如下。我只包含了相关代码,并且我没有编写了自定义复制或赋值运算符。

class Solution {

public:

    Solution() {
        stream.setNewSeed(seedShift+static_cast<long>(12345));
        ++seedShift;
    }

    RandomNumberStream stream;

private:

    static long seedShift = 0;
};

这里的重点是我希望Solution 的每个新实例都有不同的随机数流。这行得通。

然而,问题是在某些地方我从std::vector&lt;Solution&gt; 复制Solution 的实例,稍微修改它,然后将副本推送到相同的std::vector&lt;Solution&gt;。发生这种情况时,我有两个具有相同随机数种子的 Solution 实例,灾难随之而来。

如何使stream.setNewSeed(seedShift+static_cast&lt;long&gt;(12345));++seedShift; 语句在被推送到向量上的复制Solution 实例中运行?

【问题讨论】:

  • 你说你没有写过这些。为什么不呢?
  • 因为我是新手,不确定是否需要这些...尽管我怀疑它们可能是。如果需要,我不知道怎么写
  • 您需要实现复制构造函数,操作与默认构造函数相同。
  • 但是,当我实现复制构造函数时,我是否需要编写代码来复制所有其他类成员(上面未显示)?仅供参考:我没有任何指针作为成员,所以这里不应该需要深拷贝(或其他任何名称)。
  • 这取决于你拥有什么样的成员,但你可以编写一个通用函数来执行通用操作并从两者中调用它。

标签: c++ vector copy-constructor assignment-operator


【解决方案1】:

推入vector 将使用复制构造函数(或移动构造函数,但我们将使其简单并假设它现在使用复制构造函数)。这有签名:

Solution(const Solution& rhs);

然后您可以相当简单地实现此逻辑:

Solution(const Solution& rhs)
{ 
     stream.setNewSeed(seedShift + 12345L);
     ++seedShift;
}

注意如果你实现了这个,你可能也应该实现复制赋值运算符:

Solution& operator=(const Solution& rhs)
{
    if(this != &rhs) {
        stream.setNewSeed(seedShift+static_cast<long>(12345));
        ++seedShift;
    }
    return *this;
}

【讨论】:

    【解决方案2】:

    重载赋值运算符。注意 - 这也意味着当您从向量中读取值和/或复制向量本身时,随机数种子也会再次发生变化。

    class Solution {
    
    public:
    
        Solution() {
            stream.setNewSeed(seedShift+static_cast<long>(12345));
            ++seedShift;
        }
    
        Solution& operator=(Solution& other)
        {
            stream.setNewSeed(seedShift+static_cast<long>(12345));
            ++seedShift;
    
    
            x = other.x;
            y = other.y;
            z = other.z;
    
    
            return *this;
        }
    
        RandomNumberStream stream;
    
    private:
    
        static long seedShift = 0;
    };
    

    【讨论】:

    • 假设还有其他成员变量,比如int Solution::x。那么,当我复制Solution 实例时,是否需要在自定义复制构造函数中编写代码才能复制Solution::x 的值?
    • @synaptik - 绝对是的。
    • 好的,所以没有简单的方法可以将代码添加到默认的复制构造函数中。如果您希望以任何方式实现非默认行为,则必须完全定义复制时发生的所有事情。对吗?
    • 使用vectors 通常需要MoveConstructableCopyConstructable。您想在这里实现复制构造函数;赋值运算符可以说不那么重要,尽管应该实现它以保留最小意外的原则。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多