如何防止在for_each结束时调用复制构造函数?

时间:2014-03-15 17:08:37

标签: c++ c++11 visual-studio-2013

在以下代码中,我希望看到COD,但实际输出为CODD。我最终确定存在对复制构造函数的隐藏调用,因此输出现在为COUDD

虽然我已经发现为什么额外的析构函数调用我不明白它为什么生成它并且阻止我修复它。我认为它必须来自for_each返回一元函数,但由于我没有通过值传递或返回(或者我认为不是),因此不应该调用复制构造函数。一切都应该参考。我可以使用指针,但由于test_enc对象应该是调用for_each期间的范围,因此引用更好。

struct test_enc
{
    test_enc(std::string& ref) : ref_(ref) {
        ref_.push_back('C');
    }
    test_enc(const test_enc& other) : ref_(other.ref_) {
        ref_.push_back('U');
    }
    ~test_enc() {
        ref_.push_back('D');
    }
    void operator()(const char byte) {
        ref_.push_back('O');
    }
    test_enc& operator=(const test_enc&) = delete;
    std::string& ref_;
};

TEST(CheckTestEncoderEncodesExactlyOneByte)
{
    const std::string unencoded_string("M");
    std::string encoded_string;
    std::for_each(unencoded_string.begin(), unencoded_string.end(), test_enc(encoded_string));
    CHECK_EQUAL(3U, encoded_string.size());
    CHECK_EQUAL("COD", encoded_string); // get "COUDD"
}

如何在没有不需要的复制构造函数的情况下调用test_enc?

3 个答案:

答案 0 :(得分:5)

std::for_each按价值获取其一元仿函数。所以你不能避免复制,但你可以使用std::reference_wrapper模仿参考语义:

#include <functional>

std::string encoded_string;
test_encoded test_str(encoded_string);
std::for_each(unencoded_string.begin(), 
              unencoded_string.end(), 
              std::ref(test_str));

答案 1 :(得分:3)

尝试使用std::reference_wrapper

test_enc func(encoded_string);
std::for_each(unencoded_string.begin(), unencoded_string.end(),
              std::ref(func));

包装器的行为类似于引用,但允许根据需要复制它(不影响底层对象)。

答案 2 :(得分:0)

std::for_each返回std::move(f)。您的test_enc不可移动,因此会返回副本。添加移动构造函数并移动赋值运算符以防止复制。