diff --git a/include/aidge/backend/TensorImpl.hpp b/include/aidge/backend/TensorImpl.hpp
index f3fa4ef5164a2eed7caaa7baa7f83e7ed00403b8..e11a6d26fd8d2977cbee39719ce32c8bf98cb057 100644
--- a/include/aidge/backend/TensorImpl.hpp
+++ b/include/aidge/backend/TensorImpl.hpp
@@ -182,6 +182,17 @@ public:
     */
     inline std::size_t size() const noexcept { return mNbElts; }
 
+    /**
+     * @brief Return the current capacity of the tensor, i.e. the actual memory
+     * currently being allocated. It can be different from the size:
+     * - Capacity can be 0 if the tensor memory was not yet initialized (because
+     *   of lazy initialization, memory is allocated only when it needs to be
+     *   accessed the first time).
+     * - Capacity can be > size if the tensor was downsized but memory was not
+     *   reallocated.
+    */
+    virtual std::size_t capacity() const noexcept = 0;
+
     /**
      * @brief Return the size (in bytes) of one element (scalar).
     */
diff --git a/include/aidge/backend/cpu/data/TensorImpl.hpp b/include/aidge/backend/cpu/data/TensorImpl.hpp
index e9ad19291cc3907b3ef4a92370a3bafcabf37545..ff5a4fc4b8fe728efd517a74d3a9613a97e8809b 100644
--- a/include/aidge/backend/cpu/data/TensorImpl.hpp
+++ b/include/aidge/backend/cpu/data/TensorImpl.hpp
@@ -43,6 +43,8 @@ public:
         return std::make_shared<TensorImpl_cpu<T>>(device, dims);
     }
 
+    inline std::size_t capacity() const noexcept override final { return mData.size(); }
+
     inline std::size_t scalarSize() const noexcept override final { return sizeof(T); }
 
     void zeros() override final;
diff --git a/src/backend/TensorImpl.cpp b/src/backend/TensorImpl.cpp
index ee2f82a9cf847bfc6fe51e8d8b621e53a4c93cf4..335122d0583d355b6aab1649b5e8122c16eef15b 100644
--- a/src/backend/TensorImpl.cpp
+++ b/src/backend/TensorImpl.cpp
@@ -15,7 +15,9 @@
 #include "aidge/utils/ErrorHandling.hpp"
 
 void Aidge::TensorImpl::copyFrom(const TensorImpl& srcImpl, NbElts_t length, NbElts_t srcOffset, NbElts_t dstOffset) {
-    if (&srcImpl == this && srcOffset == dstOffset) {
+    // Returns if src and dst are the same
+    // OR if src capacity is 0 (no valid data must be copied)
+    if ((&srcImpl == this && srcOffset == dstOffset) || srcImpl.capacity() == 0) {
         return;
     }
 
@@ -24,7 +26,7 @@ void Aidge::TensorImpl::copyFrom(const TensorImpl& srcImpl, NbElts_t length, NbE
             // Same backend, but different device
             copyFromDevice(srcImpl.rawPtr(srcOffset), srcImpl.device(), length, dstOffset);
         }
-        else if (srcImpl.hostPtr() != nullptr) {
+        else if (srcImpl.hostPtr() != nullptr) { // capacity() is > 0 so hostPtr() will not assert
             // Different backend, but input is valid on host
             copyFromHost(srcImpl.hostPtr(srcOffset), length, dstOffset);
         }