首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ for_each 配合 std::multiplies 為何無法修改容器元素?

     編輯:程式設計綜合問答

現象重現

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>

int main() {
    std::vector<int> vec;
    int i;
    while (std::cin >> i) vec.push_back(i);
    
    // 嘗試將每個元素乘以 2
    std::for_each(vec.begin(), vec.end(),
        std::bind(std::multiplies<int>(), std::placeholders::_1, 2));
    
    // 輸出結果
    std::for_each(vec.begin(), vec.end(),
        [](int a){ std::cout << a << " "; });
}

輸出的數值並未變為 2 倍,改用 Lambda 表達式 [](int a){ a = a * 2; } 同樣無效。

根本原因

std::for_each 的一元操作接受的是元素的副本(傳值),而非引用。無論是 std::bind 產生的函數物件,還是 Lambda,若參數類型為 T 而非 T&,修改只會影響副本,不會寫回容器。

正確寫法

// 方法 1:Lambda 使用引用參數
std::for_each(vec.begin(), vec.end(), [](int &a){ a *= 2; });

// 方法 2:使用 std::transform 並寫回原容器
std::transform(vec.begin(), vec.end(), vec.begin(),
    std::bind(std::multiplies<int>(), std::placeholders::_1, 2));

// 方法 3:範圍 for 循環(C++11 以降最簡潔)
for (auto &x : vec) x *= 2;

關鍵點總結

  • for_each 只保證遍歷,不保證可修改元素,除非操作接受引用。
  • transform 專為「轉換並寫回」設計,輸出迭代器可指向原容器。
  • 現代 C++ 推薦使用範圍 for 循環,語義清晰且效率相當。

理解「傳值 vs 傳引用」與演算法語義差異,能避免此類看似合法實則無效的代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved