2016-02-16 97 views
1

看看這個代碼:C++可變參數的參數問題

的StdAfx.h:

#pragma once 

#include <stdarg.h> 

template<class T> 
class DArray { 
private: 
    T* elements; 
    int dimensions, length; 
    int* lengths; 

public: 
    DArray() { 
     dimensions = 0; 
     length = 0; 
    } 

    DArray(int dims, ...) { 
     va_list args; 
     va_start(args, dims); 
     dimensions = dims; 
     lengths = new int[dims]; 
     length = 1; 
     for (int i = 0; i < dims; i++) { 
      lengths[i] = va_arg(args, int); 
      length *= lengths[i]; 
     } 
     va_end(args); 
     elements = new T[length]; 
    } 

    T get(...) { 
     va_list args; 
     va_start(args, dimensions); 
     int weight = 1; 
     int index = va_arg(args, int); 
     for (int i = 1; i < dimensions; i++) { 
      weight *= lengths[i - 1]; 
      index += va_arg(args, int) * weight; 
     } 
     va_end(args); 
     return elements[index]; 
    } 

    void set(T value, ...) { 
     va_list args; 
     va_start(args, dimensions); 
     int weight = 1; 
     int index = va_arg(args, int); 
     for (int i = 1; i < dimensions; i++) { 
      weight *= lengths[i - 1]; 
      index += va_arg(args, int) * weight; 
     } 
     va_end(args); 
     elements[index] = value; 
    } 

    ~DArray() { 
     if (lengths != nullptr) 
      delete[] lengths; 
     //thanks to an answer pointing out I forgot to add this part: 
     if (elements != nullptr) 
      delete[] elements; 
    } 
}; 

Main.cpp的:

#include "stdafx.h" 
#include <iostream> 

DArray<int> generateRandomMatrix(int columns, int rows) { 
    int x, y; 
    DArray<int> matrix = DArray<int>(2, columns, rows); 
    for (y = 0; y < rows; y++) { 
     for (x = 0; x < columns; x++) 
      matrix.set(rand(), x, y); 
    } 
    return matrix; 
} 

int main() { 
    int x, y; 
    DArray<int> matrix; 
    do { 
     matrix = generateRandomMatrix(10, 5); 
     for (y = 0; y < 5; y++) { 
      for (x = 0; x < 10; x++) 
       printf("%d", matrix.get(x, y)); 
     } 
     printf("\n\nPress Enter to restart...\n"); 
     getchar(); 
    } while (true); 
    return 0; 
} 

出於某種原因,這對我的生活我不明白,當從generateRandomMatrix()內調用matrix.set()時,索引變量的負值爲-462266869,這導致索引超出界限異常。

如果只有正參數傳遞給函數,index如何爲負?

(這裏是局部變量的截圖看,窗口,它的價值:http://i.imgur.com/LfGQ8OF.png

+0

通常這意味着溢出。 – AndyG

+0

我無法理解如何從兩個簡單的單位數整數參數發生溢出:/ –

+0

您沒有遵循三/五規則,這是值得的。 – chris

回答

2

在成員函數set()

va_start(args, dimensions); 

應該

va_start(args, value); 
+0

不,尺寸標記了參數元素的數量。在評估索引之後,值只是設置*的值。 –

+1

「va_start」的第二個參數必須是函數參數列表中的最後一個命名參數。這就是告訴代碼在哪裏可以找到可變參數。 –

+0

哦,讓我解決它然後... –

1

generateRandomMatrix回報DArray<int>,但你沒有operator =,也沒有拷貝構造函數。

在這種情況下,返回只是複製本地類,但然後調用本地DArray矩陣的析構函數並刪除分配。

要解決它,您應該實現複製構造函數和operator =。如果你正在使用C++ 11,考慮移動運算符。

順便說一句:你有內存泄漏,因爲elements數組沒有刪除。

+0

所以,如果我使用類指針而不是類本身,你是在暗示它會影響實例方法參數? –

+0

'generateRandomMatrix'結尾處的dtor中刪除了長度數組。所以它不存在於'printf(「%d」,matrix.get(x,y));'從main調用。 – SHR

+0

但set()方法發生異常... –

0

的問題已經解決了,我想感謝2個回答我有。有兩件事情必須是固定的:

  1. 首先的va_start(參數,值)應該被用來作爲的va_start顯然需要顯式指定作爲第二個參數的最後一個參數。

新方法是:

T get(int index, ...) { 
    va_list args; 
    va_start(args, index); 
    int weight = 1; 
    for (int i = 1; i < dimensions; i++) { 
     weight *= lengths[i - 1]; 
     index += va_arg(args, int) * weight; 
    } 
    va_end(args); 
    return elements[index]; 
} 

void set(T value, ...) { 
    va_list args; 
    va_start(args, value); 
    int weight = 1; 
    int index = va_arg(args, int); 
    for (int i = 1; i < dimensions; i++) { 
     weight *= lengths[i - 1]; 
     index += va_arg(args, int) * weight; 
    } 
    va_end(args); 
    elements[index] = value; 
} 
  • 析構函數被調用,打破了功能。修改主要方法和generateRandMatrix()以使用DArray *而不是DArray與第一個修復集合在一起解決了問題! :D
  • 非常感謝所有在這個問題上花時間的人。