You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求示例说明:小型自定义类型传值并非最佳实践

Why Even Small User-Defined Types Should Avoid Pass-by-Value

Great question! Scott Meyers' guidance in Effective C++ is super important here—don’t mistake "small memory size" for "cheap to copy" when dealing with user-defined types. Let’s walk through a concrete example to see exactly why pass-by-value can be surprisingly costly, even for tiny custom objects.

First, let’s clarify the core difference: built-in types like int or char are trivial to copy—their copy is just a raw bitwise memory copy with zero hidden overhead. But user-defined types, no matter how small their footprint, can have hidden copy costs that add up quickly. Even if your object is only a few bytes, copying it might trigger constructor/destructor calls, deep copies of internal data, or other operations that aren’t obvious at first glance.

Example: A "Small" Type with Expensive Copy Semantics

Let’s create a simple custom type that looks tiny on the surface, but has expensive copy behavior:

#include <iostream>
#include <string>

// This type is only the size of a pointer (sizeof(SmallType) == sizeof(void*))
class SmallType {
private:
    std::string* internal_string;
public:
    // Constructor: Allocates a new string on the heap
    SmallType(const std::string& str) : internal_string(new std::string(str)) {
        std::cout << "✅ Constructing SmallType\n";
    }

    // Copy Constructor: Performs a deep copy of the internal string
    SmallType(const SmallType& other) : internal_string(new std::string(*other.internal_string)) {
        std::cout << "⚠️ COPYING SmallType (deep copy in progress!)\n";
    }

    // Destructor: Cleans up the heap-allocated string
    ~SmallType() {
        delete internal_string;
        std::cout << "❌ Destroying SmallType\n";
    }

    // Getter for the internal string
    const std::string& get_content() const {
        return *internal_string;
    }
};

// Function that takes SmallType by VALUE
void handle_by_value(SmallType val) {
    std::cout << "Processing value: " << val.get_content() << "\n";
}

// Function that takes SmallType by CONST REFERENCE
void handle_by_ref(const SmallType& val) {
    std::cout << "Processing reference: " << val.get_content() << "\n";
}

int main() {
    SmallType my_obj("Hello, Stack Overflow!");
    std::cout << "\n--- Calling handle_by_value ---\n";
    handle_by_value(my_obj);
    std::cout << "\n--- Calling handle_by_ref ---\n";
    handle_by_ref(my_obj);
    return 0;
}

What Happens When We Run This?

Here’s the output you’ll see:

✅ Constructing SmallType

--- Calling handle_by_value ---
⚠️ COPYING SmallType (deep copy in progress!)
Processing value: Hello, Stack Overflow!
❌ Destroying SmallType

--- Calling handle_by_ref ---
Processing reference: Hello, Stack Overflow!

❌ Destroying SmallType

Breaking Down the Difference

  • Pass-by-value: When we pass my_obj to handle_by_value, a full copy of SmallType is created. This triggers the copy constructor, which has to allocate new heap memory and copy the entire std::string content—way more work than a simple bitwise copy. When the function finishes, the copied parameter is destroyed, adding another destructor call.
  • Pass-by-const-reference: When using pass-by-reference, no copy is made at all. We just reference the original object directly. No extra constructor/destructor calls, no heap allocation, no string copying—just a lightweight reference to the existing data.

Even Without Dynamic Memory, Costs Can Add Up

This example uses dynamic memory, but even small custom types without heap allocations can have hidden costs. For instance:

  • If your type has member variables that are themselves user-defined types with expensive copies
  • If your copy constructor includes side effects like logging, thread synchronization, or database calls
  • If you’re passing the object frequently (e.g., in a loop), the cumulative cost of repeated copies becomes impossible to ignore

The key takeaway: Built-in types are cheap to copy because their copy is a trivial bitwise operation. User-defined types, however, can have arbitrary copy logic that makes pass-by-value expensive—even if they’re small in size.

内容的提问来源于stack exchange,提问作者Farsan Rashid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:49:15